You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

结构体内外空数组sizeof差异及结构体内存对齐疑问

关于C语言零长度数组的两个常见疑问解答

先补全可编译的代码(原代码缺少stdint.h头文件,uint32_t等标准整数类型需要它):

#include <stdio.h>
#include <stdint.h>

struct Obj {
    char a;
    uint32_t b;
    uint8_t c;
    uint64_t d[0];
};
struct Obj1 {
    uint64_t d[0];
};
int main() {
    uint64_t a[0];
    printf("%d\n", sizeof(struct Obj)); // 输出16
    printf("%d\n", sizeof(a)); // 输出16
    printf("%d\n", sizeof(struct Obj1)); // 输出16
    // C++环境下的输出(注释内容)
    //cout << sizeof(Obj) << endl; // 16
    //cout << sizeof(a) << endl; // 0
    //cout << sizeof(Obj1) << endl; // 0
}

疑问1:结构体中零长度数组d为何未紧跟uint8_t成员c?

这是结构体内存对齐规则和零长度数组的特性共同作用的结果:

  • 先计算没有d[0]时struct Obj的大小:
    • char a占1字节,为了对齐后续的uint32_t b(对齐要求4字节),编译器会自动填充3字节,此时总长度4;
    • uint32_t b占4字节,总长度变为8;
    • uint8_t c占1字节,此时总长度9,结构体默认会按最大成员的对齐要求(这里是uint32_t的4字节)对齐,所以再填充3字节,最终总长度12字节。
  • 加入uint64_t d[0]后,虽然这个零长度数组本身不占用存储空间,但它的元素类型是uint64_t(对齐要求8字节),这会把整个结构体的对齐要求提升到8字节。原来的12字节不是8的倍数,所以编译器会再填充4字节,让结构体总长度变为16字节——这就是d没有紧跟c的原因,中间的填充字节是为了满足8字节的整体对齐要求。

疑问2:零长度数组在结构体内外的sizeof结果为何不同?C++环境下差异更大?

这本质是C和C++标准对零长度数组的定义与支持逻辑不同:

C语言中的行为

零长度数组是GCC等编译器支持的扩展特性(不属于C标准但广泛应用):

  • 当它作为结构体的最后一个成员时,sizeof计算结构体大小会考虑该数组元素类型的对齐要求,但不会计算数组本身的大小(所以struct Obj从12字节变成16字节,struct Obj1因为要满足uint64_t的对齐要求,编译器将其大小设为16字节——不同编译器可能有细微差异,但核心是保证内存对齐);
  • 当零长度数组是单独的变量(比如main里的uint64_t a[0]),其sizeof结果是编译器定义的,你代码中输出16是特定编译器的实现(比如部分编译器会将其处理为元素类型大小的两倍),这不属于标准强制规定的行为。

C++中的行为

C标准不允许零长度数组(C中实现类似功能用柔性数组uint64_t d[];),所以注释里的行为是编译器的兼容处理:

  • 结构体中的零长度数组可能被编译器按C的规则处理(所以sizeof(Obj)还是16);
  • 单独的零长度数组a[0],编译器会按C++的逻辑返回sizeof为0,甚至直接报错(取决于编译器设置)。

这种零长度数组的实用场景

这个特性在Linux内核等底层开发中非常常用,用来实现柔性数组——让结构体后面紧跟一块连续的内存作为数组使用,示例代码如下:

// 分配内存:结构体大小 + 1024个uint64_t元素的大小
struct Obj *o1 = malloc(sizeof(struct Obj) + 1024 * sizeof(uint64_t));
// 直接通过结构体的零长度数组成员访问后面的内存
o1->d[123] = 0x12345678;

这种方式比用指针成员指向独立数组更高效:内存连续避免了缓存失效,同时节省了指针成员占用的存储空间。

内容的提问来源于stack exchange,提问作者BAKE ZQ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 06:47:26