fed*_*evi 3 c struct pointers compilation
假设定义了 2 个结构体,如下所示:
typedef struct {
T x;
T y;
} A;
typedef struct {
A a;
T z;
} B;
Run Code Online (Sandbox Code Playgroud)
我可以将指向结构 B 的指针视为指向结构 A 的指针吗?
实际上,这是可靠的/标准的/可移植的/编译器不变的:
B b = {{1,2},3};
A * a = &b;
print(a->x);
print(a->y);
Run Code Online (Sandbox Code Playgroud)
C17 6.7.2.1 指出了这一点(强调我的):
在结构体对象中,非位域成员和位域所在的单元的地址按照它们声明的顺序递增。指向结构对象的指针经过适当转换后,指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。
这意味着您必须将对象的指针“适当地转换”B b为其第一个成员的类型。此转换不会隐式发生,您必须通过显式强制转换来完成此操作:
A * a = (A*)&b;
Run Code Online (Sandbox Code Playgroud)
根据上面引用的部分,这样做是明确定义且安全的。
同样,编译器不允许假设指向的指针A和指向的指针B没有别名。有效类型 6.5.7 的规则(“严格别名”)给出了这种情况的例外:
对象的存储值只能由具有以下类型之一的左值表达式访问:
...
- 其成员中包含上述类型之一的聚合或联合类型
例如,在优化期间,void func (B* b)不允许调用该函数的编译器假设该函数extern A a;未更改某些其他翻译单元中定义的外部行数变量。