使用指向结构的别名数组,而不违反标准

阅读本文我理解你可以使用别名结构(不违反标准),如果它们具有兼容的成员,即给定以下结构:

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_tb现在由不兼容( 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数组转换为结构指针。
你需要关心的是:

  • 数组足够大
  • 成员对齐