我使用sizeof来获取C中结构的大小,但我得到的结果是意外的。
struct sdshdr {
int len;
int free;
char buf[];
};
int main(){
printf("struct len:%d\n",(sizeof(struct sdshdr)));
return 0;
} //struct len:8, with or without buf
我的问题是为什么buf
没有占用任何空间,为什么64位CPU上int
类型的大小仍为4?
这是gcc -v
的输出:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.4.0
Thread model: posix
答案 0 :(得分:52)
[]是一个灵活的数组成员。它们不计入结构的总大小,因为C标准明确地这样说:
6.7.2.1/18
作为一种特殊情况,具有多个命名成员的结构的最后一个元素可以 有一个不完整的数组类型;这被称为灵活的阵列成员。在大多数情况下, 灵活的数组成员被忽略。特别是,结构的大小就像是 省略了灵活的数组成员,除了它可能有更多的尾随填充 遗漏意味着。
这是故意设计的,因为灵活数组成员的目的是允许您在结构之后动态分配尾随数据。 (当结构是文件头,协议头等时。)
Example包括有关非标准gcc扩展和旧前C99" struct hack"的讨论。
答案 1 :(得分:12)
从C99开始,可以省略结构末尾的数组大小。出于sizeof(struct)
的目的,此数组看起来大小为零(尽管它的存在可能会为结构添加一些填充),但目的是使其长度灵活,即,为结构分配空间必须在最后为数组分配所需的额外空间量。 (为了避免超出范围,数组的实际分配长度应存储在某处。)
在C99之前,在结构的末尾有一个大小为1(或编译器允许的0)的数组是一个相当普遍的hack,然后为它分配更多空间,因此C99通过引入明确允许这种做法没有给出大小的flexible array member。
答案 2 :(得分:2)
作为GNU c扩展,您有零长度数组:
作为GNU扩展,元素的数量可以小到零。零长度数组作为结构的最后一个元素很有用,它实际上是一个可变长度对象的标题:
例如,请考虑The gnu c manual
中的此代码 struct line
{
int length;
char contents[0];
};
{
struct line *this_line = (struct line *)
malloc (sizeof (struct line) + this_length);
this_line -> length = this_length;
}
在ISO C99中,您将使用灵活的数组成员,它在语法和语义上略有不同:
灵活数组成员写为内容[],不带0。
灵活数组成员的类型不完整,因此可能无法应用sizeof运算符。 作为零长度数组原始实现的一个怪癖,sizeof的计算结果为零。
灵活数组成员可能只显示为非空的结构的最后一个成员。
包含柔性阵列成员的结构或包含这种结构的联合(可能是递归地),可能不是结构的成员或数组的元素。 (但是,GCC允许这些用途作为扩展。)
答案 3 :(得分:0)
buf
这里是flexible array member
灵活的数组成员具有不完整的类型,因此可能无法应用sizeof运算符而zero-length arrays
,sizeof evaluates to zero
的原始实现。