C++中空结构体大小非零?含0长度数组的结构体为何大小为0?
嘿,这个问题确实容易让人摸不着头脑,我来帮你拆解一下背后的逻辑~
先把你给出的代码贴出来方便对照:
#include <stdio.h> struct Empty1 { } __attribute__((packed)); struct Empty2 { size_t data[0]; } __attribute__((packed)); int main(int argc, char *argv[]) { printf("sizeof(Empty1)=%zd\n", sizeof(struct Empty1)); printf("sizeof(Empty2)=%zd\n", sizeof(struct Empty2)); return 0; }
用G++ 7.3编译运行后得到sizeof(Empty1)=1、sizeof(Empty2)=0,咱们逐个分析:
关于struct Empty1(空结构体)
首先要明确:标准C/C++并不支持空结构体,这是GCC这类编译器提供的扩展特性。那为什么它的大小是1而不是0?
核心原因是C/C++的内存模型要求每个对象必须拥有唯一的内存地址。如果空结构体大小为0,那么声明两个struct Empty1变量时,它们会占用同一个内存位置,这就违反了“每个对象都有独立地址”的底层规则。哪怕你加了__attribute__((packed))也没用——这个属性只是消除结构体的填充字节,却没法打破“对象必须有唯一地址”的硬性要求,所以编译器只能给它分配1字节的最小内存。
关于struct Empty2(含零长度数组的结构体)
size_t data[0]是GCC的另一个扩展:零长度数组。这种数组的特殊之处在于,它本身不占用任何内存空间——设计它的初衷是用来实现“柔性数组”的前置用法(不过C11标准里已经有了正式的柔性数组语法size_t data[])。
当结构体里只有一个零长度数组,且加上__attribute__((packed))消除所有可能的填充后,整个结构体的自然大小就是0。而且零长度数组本身不是一个独立的对象,它只是结构体的一个“占位符”,不会触发“对象必须有唯一地址”的限制——毕竟你不会单独声明一个零长度数组的变量,它总是依附在结构体里使用。
额外提醒
这些都是编译器的扩展特性,不属于标准C/C++的范畴,换个编译器(比如Clang或者MSVC)可能会有不同的表现。如果要写可移植的代码,最好避免依赖这些扩展~
内容的提问来源于stack exchange,提问作者ynimous

