C中sizeof的内部机制?

时间:2015-07-09 13:19:59

标签: c gcc sizeof flexible-array-member

我使用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  

4 个答案:

答案 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 arrayssizeof evaluates to zero的原始实现。