假设我有来自外部库的以下类型:
union foreign_t {
struct {
enum enum_t an_enum;
int an_int;
} header;
struct {
double x, y;
} point;
};
假设以下代码片段将在不同平台和不同编译器上按预期工作是否安全?
struct pair_t {
double x, y;
};
union foreign_t foreign;
struct pair_t *p_pair;
p_pair = (struct pair_t *) &foreign;
p_pair->x = 1234;
p_pair->y = 4321;
/* Expected result: (1234, 4321) or something like that */
printf("(%lf, %lf)", foreign.point.x, foreign.point.y);
编辑:
按照严格的别名建议,我做了以下测试:
#include <stdint.h>
#include <stdio.h>
int main()
{
uint16_t word = 0xabcd;
uint8_t tmp;
struct {
uint8_t low;
uint8_t high;
} *byte = (void *) &word;
tmp = byte->low;
byte->low = byte->high;
byte->high = tmp;
printf("%x\n", word);
return 0;
}
上面这段看似无辜的代码并不可靠:
$ gcc -O3 -fno-strict-aliasing -otest test.c
$ ./test
cdab
$ gcc -O3 -fstrict-aliasing -otest test.c
$ ./test
abcd
开发人员不得安宁...
最佳答案
如您所写,我相信它应该适用于任何体系结构上的几乎任何编译器。但是,我确实认为它在技术上违反了 strict aliasing规则。您在不相关的指针类型之间进行转换,因此过度激进的优化器可能会重新排序某些内存读写,因为它假定某些指针不会相互混淆。
不幸的是,假设您不能修改 foreign_t
的定义,我不认为有什么方法可以使这段代码绝对防止严格的别名。由于内部结构没有名称,因此您无法构造指向它的指针,编译器将假定它是可别名的。不过在实践中,我认为您的代码不会出现问题。
关于c - C 结构/union 的可移植性问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1575355/