考虑以下代码:
typedef struct { char byte; } byte_t;
typedef struct { char bytes[10]; } blob_t;
int f(void) {
blob_t a = {0};
*(byte_t *)a.bytes = (byte_t){10};
return a.bytes[0];
}
在返回语句中,这会导致别名问题吗?需要注意的是,a.bytes
解引用了一个与 patch
赋值不同别名的类型,但另一方面,[0]
解引用了一个与赋值相同别名的类型。
我可以构造一个稍微大一些的例子,其中gcc -O1 -fstrict-aliasing
确实使函数返回0。我想知道这是否是gcc的bug,如果不是,我该如何避免这个问题(在我实际的例子中,赋值发生在一个单独的函数中,因此两个函数在隔离的情况下看起来都很简单)。
以下是一个更长更完整的测试示例:
#include <stdio.h>
typedef struct { char byte; } byte_t;
typedef struct { char bytes[10]; } blob_t;
static char *find(char *buf) {
for (int i = 0; i < 1; i++) { if (buf[0] == 0) { return buf; }}
return 0;
}
void patch(char *b) {
*(byte_t *) b = (byte_t) {10};
}
int main(void) {
blob_t a = {0};
char *b = find(a.bytes);
if (b) {
patch(b);
}
printf("%d\n", a.bytes[0]);
}
gcc -O1 -fstrict-aliasing
编译后的结果为 0
byte_t
?你是不是想说uint8_t
? - MightyPork*(byte_t *)a.bytes
中存在别名违规。 - Eric Postpischila.bytes
是一个指向char
的指针(由于数组的自动转换)。将该char
作为char_t
访问,访问的是一种它不是的类型,并且这不是别名规则中列出的任何允许的类型之一。因此,它违反了别名规则。 - Eric Postpischil