不动一类与另一种类型的值违反严格走样?
-
20-09-2019 - |
题
这是否违反严格别名规则移动任何类型的项目周围使用uint32_t的,然后看他们回来呢?如果是这样,它也严格违反重叠规则从uint32_ts的阵列的任何类型的阵列,以memcpy的,然后读取元件背面?
在以下代码示例说明这两种情况下:
#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
int main(void) {
const char *strings[5] = {
"zero", "one", "two", "three", "four"
};
uint32_t buffer[5];
int i;
assert(sizeof(const char*) == sizeof(uint32_t));
memcpy(buffer, strings, sizeof(buffer));
//twiddle with the buffer a bit
buffer[0] = buffer[3];
buffer[2] = buffer[4];
buffer[3] = buffer[1];
//Does this violate strict aliasing?
const char **buffer_cc = (const char**)buffer;
printf("Test 1:\n");
for (i=0; i<5; i++)
printf("\t%s ", buffer_cc[i]);
printf("\n");
//How about this?
memcpy(strings, buffer, sizeof(strings));
printf("Test 2:\n");
for (i=0; i<5; i++)
printf("\t%s ", strings[i]);
printf("\n");
return 0;
}
请忽略我的32位平台的设想。此外,如果元素不是大小uint32_t的一样,我知道他们垫和复制uint32_t的的正确数量。我的问题集中在是否不这样做违反了严格别名。
解决方案
在第一环路确实技术上违反严格别名 - 它通过类型uint32_t
的左值访问char *
对象。很难看到任何优化器将如何使你的问题在这种特殊情况下,虽然。如果你改变了一点,所以你在做一样的东西:
printf("\t%s ", buffer_cc[0]);
buffer[0] = buffer[3];
printf("\t%s ", buffer_cc[0]);
您可能看到相同的字符串印刷两次。 - 由于优化器将其权限只负载buffer_cc[0]
内一次到寄存器中,因为第二线仅修改类型uint32_t
的目的
第二环路,即memcpy
s他们回来,是细
其他提示
和buffer_cc[0]
strings[3]
(例如)是引用相同的存储器位置,但是相同类型的,从而不违反严格别名指针。 buffer[0]
不是指针,从而不违反严格混叠。解引用指针时的混叠出现的优化,因此我不希望这会导致问题。
当你暗示了在代码和你的问题的最后一段,在示例代码中的实际问题时,指针和uint32_t的大小不同就产生了。
此外,可以随时别名char*
以指向另一种类型的不违反严格别名,虽然不是反之亦然。
不隶属于 StackOverflow