我对sizeof()
C 中的输出感到困惑。假设我有:
struct foo {
char a;
char b;
char c;
char d[0];
};
我希望sizeof(struct foo)
是 4。但是,它在使用 gcc 编译后返回 3。此外,在使用严格设置编译代码时-pedantic-errors
,我得到编译器错误。
有人可以帮我理解这种行为吗?
我对sizeof()
C 中的输出感到困惑。假设我有:
struct foo {
char a;
char b;
char c;
char d[0];
};
我希望sizeof(struct foo)
是 4。但是,它在使用 gcc 编译后返回 3。此外,在使用严格设置编译代码时-pedantic-errors
,我得到编译器错误。
有人可以帮我理解这种行为吗?
数组大小为 0 是不合法的。C 标准中关于数组声明符的第 6.7.6.2p1 节指出:
除了可选的类型限定符和关键字 static 之外,
[
and]
可以分隔表达式或*
. 如果它们分隔了一个表达式(它指定了一个数组的大小),则该表达式应为整数类型。如果表达式是常量表达式,它的值应大于零。 元素类型不应是不完整类型或函数类型。可选类型限定符和关键字 static 应仅出现在具有数组类型的函数参数的声明中,然后仅出现在最外层的数组类型派生中。
所以因为这违反了约束,所以这个定义调用了未定义的行为。
话虽如此,一些编译器允许零长度数组作为 a 的最后一个成员struct
作为扩展。 GCC 这样做。在这种情况下,它的工作方式与灵活数组成员相同。
执行此操作的标准兼容方法是将大小留空:
struct foo {
char a;
char b;
char c;
char d[];
};
在这两种情况下,灵活数组成员都不包含在结构的大小中,这就是为什么你得到 3 而不是 4 的大小(尽管结构中是否存在填充取决于实现)。这也意味着这样的结构不能是数组的成员(至少在没有一些可疑的手动指针操作的情况下不能)。
使用这种结构的方式是为它动态分配空间以及最后一个成员的一些元素。例如:
struct foo *my_foo = malloc(sizeof(*my_foo) + (sizeof(char) * number_of_elements));
char d[0]
是一个大小为 0 的字符数组。这意味着它不占用任何空间,因为sizeof(char) * 0 = 0
.