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