C++结构体与共用体大小计算及内存对齐规则详解

Finn
Finn
发布时间:2026-10-16| 6人浏览过
原创

C++中的结构体和共用体在内存布局上遵循严格的对齐规则。本文通过代码对比展示不同成员排序对结构体大小的影响,解释对齐数与最大对齐数的概念,并详细拆解结构体、共用体及枚举类型的内存大小计算方法,帮助开发者优化内存使用。

一、结构体内存对齐规则

结构体的内存大小不仅取决于成员的总和,还受到内存对齐规则的显著影响。在实际开发或面试中,理解如何通过代码验证和调整结构体成员顺序至关重要。

第1步:基础结构体大小验证

目的:观察相同数据类型但不同排列顺序的结构体所占内存差异。

我们定义四个包含字符、整型及数组的结构体 Node1 至 Node4,代码如下:

#include <stdio.h>
struct Node1{
    char c1;
    int val1;
    char c2;
};
struct Node2{
    char c1;
    char c2;
    int val1;
};
struct Node3{
    char c1;
    char array[10];
};
struct Node4{
    char val1;
    int arrar[10];
};
int main(){
    printf("Node1 size = %d\n",sizeof(struct Node1));
    printf("Node2 size = %d\n",sizeof(struct Node2));
    printf("Node3 size = %d\n",sizeof(struct Node3));
    printf("Node4 size = %d\n",sizeof(struct Node4));

    return 0;
}

运行上述代码后,得到的内存大小结果如下:

第2步:明确对齐数与最大对齐数

要正确计算结构体大小,首先需要掌握两个核心概念:

  • 对齐数:结构体中每个成员的对齐倍数。例如,char 的对齐数为 1,int 的对齐数为 4。对于数组,其对齐数是其内部元素类型的大小,而非数组总长度。因此在 Node3 中,对齐数为 {1, 1};Node4 中对齐数为 {1, 4}。
  • 最大对齐数:结构体内部所有对齐数中的最大值。该值通常受编译器限制(如 GCC 通常为 4,VS 为 8)。计算时取“结构体最大对齐数”与“编译器对齐数”的较小值。本例以 GCC 为例,最大对齐数即结构体内部的数值最大值。

第3步:结构体内存分配逻辑与计算

结构体内存分配的核心原则是:结构体总大小必须是最大对齐数的整数倍。

当存放成员变量时,为了保证连续性,如果当前剩余空间不足以存放下一个成员(且未达到对齐边界),编译器会填充字节(Padding),使下一个成员从对齐倍数位置开始存储。这虽然浪费了少量内存,但提高了 CPU 读取效率。

基于上述原理,各结构体具体计算方式如下:

  • Node1 (12 字节):c1(1) + 填充3 + val1(4) + c2(1) + 填充3 = 12。
  • Node2 (8 字节):c1(1) + c2(1) + 填充2 + val1(4) = 8。(紧凑排列节省空间)
  • Node3 (11 字节):c1(1) + array(10) = 11。
  • Node4 (44 字节):val1(1) + 填充3 + array[10](4*10=40) = 44。

第4步:嵌套结构体的大小计算

当结构体内部包含其他结构体时,嵌套结构体的对齐数被视为其自身的最大对齐数。

#include <stdio.h>
struct Node1{
    char c1;
    int val1;
    char c2;
};
struct Node2{
    char c1;
    struct Node1 node;
    double val1;
};

int main(){
    printf("Node1 size = %d\n",sizeof(struct Node1));
    printf("Node2 size = %d\n",sizeof(struct Node2));
    return 0;
}

在此案例中:

  • Node1 的最大对齐数为 4,大小为 12。
  • Node2 包含 char, Node1(相当于 int), double。其成员对齐数为 {1, 4, 8},因此最大对齐数为 8。

Node2 的具体内存分布为:

  • c1(1) + 填充7(确保接下来的 node 从 8 的倍数地址开始)。
  • node(12) + 填充4(16是8的倍数,此处需补足至8的倍数,实际上 node 占12,加上前面的偏移量,这里为了后续 double 的对齐可能需要考虑整体结构,具体按标准补齐)。

根据常见对齐规则推算:Node2 = 1 (c1) + 7 (Pad) + 12 (node) + 4 (Pad,用于使 double 对齐,或者整体最终大小需对齐到8的倍数) + 8 (double) = 24 字节。最终结果为:

  • sizeof(Node1) = 12
  • sizeof(Node2) = 24

二、共用体(Union)内存大小计算

共用体的成员共享同一块内存区域。这意味着共用体的大小至少应能容纳最大的成员变量,同时也必须遵循内存对齐原则。

第5步:共用体示例验证

#include <stdio.h>
union un1{
    int val;
    char c;
    double d;
};
union un2{
    int val;
    char array[5];
};

int main(){
    printf("un1 size = %d\n",sizeof(union un1));
    printf("un2 size = %d\n",sizeof(union un2));
    return 0;
}

运行结果如下:

分析:

  • un1:最大成员是 double (8字节)。其自身也是 8 的倍数,故大小为 8。
  • un2:成员有 int (4字节) 和 char[5] (5字节),最大占用为 5 字节。但是,int 的对齐要求决定了整个共用体的对齐数为 4。共用体总大小必须是最大对齐数(4)的整数倍。大于等于 5 且能被 4 整除的最小数字是 8。

三、枚举(Enum)的大小

除了结构体和共用体,枚举类型的大小也常引起混淆。其大小并非固定,而是由编译器根据赋值的范围决定。

第6步:枚举大小验证

#include <stdio.h>
enum Colour {
    RED,
    GREEN,
    BLUE
};
enum ProgramLanguage {
    python = 0xffffffffff,
    c = 8,
    java
};

int main()
{
    printf("Colour size = %d\n",sizeof(enum Colour));
    printf("ProgramLanguage size = %d\n",sizeof(enum ProgramLanguage));
    return 0;
}

运行结果如下:

结果说明:

Colour 只使用了默认的小整数,编译器通常赋予其 int 的类型,故大小为 4 字节。而 ProgramLanguage 中包含了极大的数值 0xffffffffff(十六进制),超出了 32位 int 的范围,迫使编译器将其提升为更大尺寸(通常是 64位 long long),故大小变为 8 字节。这说明枚举的实际占用完全取决于具体的赋值情况。

总结

掌握 C++ 结构体的内存对齐、共用体的共享机制以及枚举的动态类型分配,能够有效避免内存泄漏或越界访问风险,并在底层编程中实现最优的资源利用率。以上就是C++结构体字节对齐和共用体大小计算的详细内容,更多关于C++内存管理机制的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。