C中sizeof的内部机制?
我使用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
types的大小仍然是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
[]是一个灵活的数组成员 。 它们不计入结构的总大小,因为C标准明确地这样说:
6.7.2.1/18
作为特殊情况,具有多个名称成员的结构的最后一个元素可能具有不完整的数组types; 这被称为一个灵活的数组成员。 在大多数情况下,灵活的数组成员被忽略。 特别是,结构的大小就好像是柔性arrays成员被省略,除了它可能具有比省略暗示的更多的尾部填充。
这是有意devise的,因为灵活的数组成员的目的是让你在结构之后dynamic分配尾随数据。 (当结构是文件头,协议头等)
例子包括讨论关于非标准的gcc扩展和旧的C99之前的“struct hack”。
从C99开始,结构数组的大小可以省略。 为了sizeof(struct)
目的,这个数组的大小看起来是零(虽然它的存在可能会增加一些填充到结构中),但是它的长度是灵活的 ,即为结构分配空间时必须分配所需数量的额外空间的数组在最后。 (为了避免超出范围,数组的实际分配长度应该存储在某个地方。)
在C99之前,在结构的最后有一个大小为1(或者编译器允许的地方为0)的数组,然后为它分配更多的空间是非常常见的,所以C99通过引入灵活数组没有大小的成员 。
作为一个GNU c扩展,你有零长度的数组:
作为一个GNU扩展,元素的数量可以小到零。 零长度数组作为结构的最后一个元素是非常有用的,它实际上是可变长度对象的头部:
例如,从gnu c手册中考虑这个代码
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。
灵活的arrays成员的types不完整,所以sizeof运算符可能不适用。 作为零长度数组原始实现的一个怪癖,sizeof的计算结果为零。
灵活的数组成员可能只能作为非空的结构的最后一个成员出现。
包含灵活数组成员的结构,或者包含这种结构的联合(可能是recursion的),可能不是结构的成员或数组的元素。 (但是,GCC允许这些使用作为扩展。)
buf
这里是一个flexible array member
灵活的数组成员有不完整的types,所以sizeof运算符可能不会被应用,而zero-length arrays
原始实现, sizeof evaluates to zero
。