我试图理解 C99 标准(C99;ISO/IEC 9899:1999 6.5/7)中以下声明的含义
An object shall have its stored value accessed only by an lvalue expression that has one of the following types 73) or 88):
(other statements unrelated to question omitted)
an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union)
考虑以下几点:
typedef struct MyComplex {
float real;
float imag;
} MyComplex;
MyComplex *carray = malloc(sizeof(*carray) * 10);
float *as_floats = (float *)carray;
这是否合法,因为 MyComplex
结构包含用于 as_floats
指针的兼容 float
类型?
反过来呢?即:
float *farray = malloc(sizeof(*farray) * 10);
MyComplex *as_complex = (MyComplex *)farray;
在这两种情况下,最终,我们在这里处理的所有内容都是 float
,所以也许没问题?我只是不确定。
我问,因为我正在处理一个遗留代码库,它到处都在做这种事情,到目前为止,一切似乎都很好。但我觉得我们在这里是在玩火。试图弄清楚我是否需要在编译器命令行上禁用严格别名。
最佳答案
(我相信)所有版本的标准纵容案例 #1 的 6.7.2.1 中的注释 13 明确。您很少会得到更明确的答案! 我的重点
Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.
http://port70.net/~nsz/c/c99/n1256.html#6.7.2.1
是的!您可以强制转换结构以直接访问其第一个成员!
为什么有人认为这比 &(carray->real)
更好尚不清楚。但这绝对是合法的。
正如另一位评论者所指出的,我在上一个问题中讨论了案例 #2。
Aliasing Arrays through structs
结论是案例 #2 是访问成员 real
的 OK 方法。
此外,如果该结构没有内部填充(取决于平台),您甚至可以通过 imag
访问数组的第二个成员。
我说的是平台相关,但其他调查没有提供任何已知平台,这样的结构会包含填充。
关于c - 与聚合或 union 类型相关的严格别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28434418/