jay*_*ica 8 c alias strict-aliasing
阅读本文我理解你可以使用别名结构(不违反标准),如果它们具有兼容的成员,即给定以下结构:
typedef struct {
uint32_t a;
uint32_t b;
} Frizzly;
Run Code Online (Sandbox Code Playgroud)
以下将破坏别名规则:
uint32_t foo(uint16_t *i) {
Frizzly *f = (Frizzly *)i;
return f->a;
}
Run Code Online (Sandbox Code Playgroud)
但以下不会:
uint32_t foo(uint32_t *i) {
Frizzly *f = (Frizzly *)i;
return f->b;
}
Run Code Online (Sandbox Code Playgroud)
因为所讨论的"聚合类型"包含与我们投入其中的指针兼容的类型,即指向类型的指针uint32_t可以被转换为包含类型成员(或成员)的结构,uint32_t而不会破坏别名规则.
首先,我是否理解正确?
其次,结构中(其他)变量的排序和类型是否重要?比如说,如果Frizzly定义如下:
typedef struct {
uint16_t b[2];
uint32_t a;
}
Run Code Online (Sandbox Code Playgroud)
在第二个示例中进行强制转换后,b现在由不兼容(uint32_t)类型的内存支持.转换是否仍然有效(或者更确切地说,通过转换指针访问值)?是否会更改任何元素a更改第一个元素的值i(以及相反的方式),就像禁用严格别名一样?
另外,如果以上内容有效,如果我有这样的结构怎么办:
typedef struct {
void *m;
uint16_t hooah[4];
} Bar;
Run Code Online (Sandbox Code Playgroud)
如果我是正确的话,以下演员会破坏别名规则:
void test(char *boo, size_t dee) {
Bar *bar = (Bar *)(boo + dee);
do_other_stuff(bar);
}
Run Code Online (Sandbox Code Playgroud)
我可以简单地通过unsigned char在结构中添加一个成员来使强制转换有效吗?换句话说,不兼容类型的转换指针通常会破坏别名规则,但由于从指向包含类型成员的结构X转换为指针的转换X是一个例外,可以从指针到X的任何转换到聚合Y简单地通过在Y中添加类型X的(可能是虚拟的)成员来生效?
(我实际上并没有在编译器中测试上面的代码片段.)
编辑:
我知道我的措辞和例子可能相当差,所以我会试着重新解释一下这个问题:如果我理解正确,指向结构的指针就可以为"X"类型的元素数组添加别名是合法的. struct包含类型为'X'的成员.现在,当取消引用结构的一个成员时,该成员是否必须是"X"类型,或者是对结构的所有成员所做的严格别名规则的例外,无论它们的类型如何,只要有一个成员合适的类型?
根据ISO/IEC9899/TC2第 6.7.2.1 节第 13 段:
指向结构对象的指针,经过适当转换后,指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然
因此,只要将结构体指针转换为第一个成员的指针类型,它就不应该违反严格别名(在第 6.5 节第 7 段中指定),也可以通过以下方式访问元素:
聚合或联合类型,其成员中包含上述类型之一(递归地包括子聚合或包含联合的成员)
但这仅适用于另一个方向(通过结构指针访问成员,而不是通过成员指针访问结构)