在嵌套结构中具有灵活的数组成员是否有效的C代码?那么,下面的示例代码是否可以保证正常运行时可以正常工作?
#include <stdio.h>
#include <stdlib.h>
struct d {
char c;
int ns[];
};
struct c {
struct d d;
};
struct b {
struct c c;
};
struct a {
int n;
struct b b;
};
int main() {
const int n = 10;
struct a *pa = malloc(sizeof(*pa) + n * sizeof(pa->b.c.d.ns[0]));
pa->n = n;
pa->b.c.d.c = 1;
for (int i = 0; i < n; ++i) {
pa->b.c.d.ns[i] = i;
}
for (int i = 0; i < n; ++i) {
printf("%d\n", pa->b.c.d.ns[i] + pa->b.c.d.c);
}
free(pa);
}
按照标准无效。我不确定它在实践中是否可靠。
C11(ISO / IEC 9899:2011)§6.7.2.1.3表示以下内容(强调我的意思):
结构或联合不得包含具有不完整或函数类型的成员(因此,结构不应包含其自身的实例,但可以包含指向其自身的实例的指针),除非结构的最后一个成员具有大于一个命名成员可能具有不完整的数组类型;这样的结构(以及可能包含递归关系的任何并集的任何并集)都不应该是结构的成员或数组的元素。
稍后,第6.7.2.1.18节阐明了以上内容是指灵活数组成员(FAM):
作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型;这称为弹性数组成员。
经过一些快速的实验,GCC和Clang都添加了正确对齐FAM所需的尾随填充,即使在struct
嵌套时也是如此,并且仅当FAM成为其他结构或数组的成员时才发出警告-Wpedantic
,因此将其表示为如果可能的话,它可能会起作用:)。不过,它感觉有点破旧。
请注意,除了最后,在任何地方都可以使用FAM。如果你这样做
struct e {
struct d d;
int n;
} e;
,则e.d.ns[0]
和e.n
可能在内存中重叠。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句