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上inttypes的大小仍然是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