讲师中心 微信公众号
AI工具推荐 视频效率加速

C++中联合体的大小是如何由其最大的成员决定的

落辰姑娘_3627

落辰姑娘_3627

发布时间:2025-09-11 11:41:01

|

432人浏览过

|

来源于php中文网

原创

联合体大小由其最大成员决定,因其所有成员共享同一内存区域,必须足够容纳最大成员并满足最严格对齐要求。结构体成员独立存储,大小为各成员之和加填充;联合体成员共享起始地址,任一时刻仅一个成员有效,大小至少为最大成员大小且为最严格对齐要求的倍数。典型应用包括节省内存(如消息负载)、实现变体类型(配合枚举)以及底层类型转换(现代C++推荐std::bit_cast替代)。

c++中联合体的大小是如何由其最大的成员决定的

C++联合体(union)的大小确实是由其所有成员中占用内存空间最大的那个成员决定的。这不是一个巧合,而是其设计哲学——节省内存——的必然结果。所有成员都共享同一块内存区域,因此这块区域必须足够大以容纳其中最大的“住客”。

解决方案

联合体的本质在于其内存共享机制。与结构体(struct)不同,结构体的成员是依次排列的,每个成员都有自己独立的内存空间,所以结构体的大小是所有成员大小之和(加上可能的填充字节)。而联合体的所有成员都从同一个内存地址开始存储。这意味着在任何给定时间,联合体只能存储其中一个成员的值。为了确保任何成员都能被完整地存储进去,编译器自然会分配一块足够大的内存区域,其大小至少要等于它所有成员中最大的那个。如果最大的成员是

double
(8字节),那么即使联合体里只有一个
char
(1字节)或
int
(4字节),整个联合体的大小也必须是8字节,因为
double
需要这8字节。

union MyUnion {
    char c;       // 1 byte
    int i;        // 4 bytes
    double d;     // 8 bytes
};
// 在大多数系统上,sizeof(MyUnion) 会是 8(或更多,由于对齐,但至少是8)。

这里其实隐含了一个重要的点,就是内存对齐。联合体的大小不仅要能容纳最大的成员,还要满足所有成员的对齐要求,特别是最大成员的对齐要求。

联合体与结构体在内存布局上的根本区别是什么?

结构体(struct)和联合体(union)在C++中都是复合数据类型,但它们在内存布局和使用方式上有着天壤之别。

立即学习“C++免费学习笔记(深入)”;

  • 结构体 (struct): 它的成员是各自独立、顺序存储的。这意味着每个成员都拥有自己独立的内存地址,即使因为内存对齐规则,成员之间可能存在一些填充(padding)字节,它们也绝不会重叠。

    sizeof(struct)
    通常是所有成员大小之和,再加上编译器为了优化访问速度和满足对齐要求而可能插入的填充字节。你可以同时访问或修改结构体中的所有成员,它们的值互不影响。这很符合我们对“一篮子”不同物品的直观理解。

  • 联合体 (union): 它的成员共享同一块内存区域,从同一个起始地址开始存储。这意味着在任何给定时刻,你只能有效地使用其中一个成员。当你给一个成员赋值后,这块共享内存区域的内容就会被这个新值覆盖,其他成员的值可能变得不可预测或无意义(如果它们类型不同)。

    sizeof(union)
    是其所有成员中最大成员的大小,并同时考虑了内存对齐的要求。我个人在初学C++时,对联合体的这种“共享”概念感到有些困惑,总觉得它像一个多面手,但又不能同时施展所有技能。后来才明白,这正是它在嵌入式系统或需要极致内存优化的场景下大放异彩的原因。它不是为了方便同时处理多种数据类型,而是为了在不同时刻用同一块内存来表示不同类型的数据。

内存对齐如何影响联合体的实际大小?

即使联合体最大的成员是X字节,但实际的

sizeof(union)
可能比X大。这是因为内存对齐的要求。每个数据类型都有一个默认的对齐要求(例如,
int
通常要求4字节对齐,
double
要求8字节对齐)。处理器在访问内存时,通常会以字长(word size)的倍数来读取数据,如果数据没有对齐到合适的地址,处理器可能需要进行多次内存访问,或者引发性能下降,甚至在某些体系结构上直接报错。

联合体作为一个整体,其起始地址必须满足其所有成员中对齐要求最严格的那个。同时,联合体的总大小也必须是其最严格对齐要求的倍数,以确保在数组中,下一个联合体实例也能正确对齐。

Publish Passwords
Publish Passwords

本地凭据保险库,集成操作系统密钥链,支持加密存储与会话级访问控制。

下载

示例:

union AlignedUnion {
    char a;   // 1 byte, 默认对齐1字节
    int b;    // 4 bytes, 默认对齐4字节
    double c; // 8 bytes, 默认对齐8字节
};
// 在大多数64位系统上,sizeof(AlignedUnion) 会是 8。
// 因为最大的成员是double (8字节),它的对齐要求是8字节。
// 所以整个union的大小必须是8的倍数,且至少能容纳8字节。

union AnotherUnion {
    char c;   // 1 byte, 默认对齐1字节
    long long ll; // 8 bytes, 默认对齐8字节
    short s;  // 2 bytes, 默认对齐2字节
};
// sizeof(AnotherUnion) 也会是 8。
// 最大的成员是long long (8字节),对齐要求是8。
// 即使char和short都在,union大小也必须是8的倍数。

这种对齐规则有时会让人觉得有点“浪费”,比如一个

char
和
long long
的联合体,实际上只有
long long
在使用时才真正需要8字节,但整个联合体却固定占8字节。但这正是为了CPU访问效率和跨平台兼容性所做的权衡。编译器在幕后为我们处理了这些细节,确保了程序的正确性和效率。

联合体在C++实际编程中有哪些典型应用场景?

联合体虽然在现代C++中被一些更安全的替代方案(如

std::variant
)所取代,但在某些特定场景下,它依然是简洁高效的选择,尤其是在需要底层控制或与C语言兼容时。

  • 节省内存: 这是联合体最直接、最核心的应用。当你知道在程序的不同阶段,同一块内存区域需要存储不同类型但不会同时使用的信息时,联合体是理想选择。例如,在一个消息处理系统中,一个消息结构可能包含不同类型的负载(文本、图片数据、控制指令),但每次只发送一种。使用联合体可以避免为每种可能的负载类型都分配独立的内存,从而显著减少内存占用。

  • 变体类型 (Variant Types): 联合体常与枚举(enum)结合使用,创建“变体”类型,即一个数据结构可以表示多种不同的数据类型。枚举用于指示当前联合体中哪个成员是活跃的,从而安全地访问正确的成员。

    enum DataType {
        INT_TYPE,
        DOUBLE_TYPE,
        STRING_TYPE // 假设是固定大小的字符串
    };
    
    struct Data {
        DataType type; // 用于指示当前活跃的类型
        union {
            int iVal;
            double dVal;
            char sVal[20]; // 固定大小字符串,避免动态内存分配的复杂性
        } value;
    };
    
    // 使用示例:
    Data myData;
    myData.type = INT_TYPE;
    myData.value.iVal = 123;
    
    // 或者
    myData.type = DOUBLE_TYPE;
    myData.value.dVal = 3.14;
    
    // 访问时需要检查类型:
    if (myData.type == INT_TYPE) {
        // 使用 myData.value.iVal
    }

    这种模式在实现类似

    std::variant
    (C++17之前)或在C语言中处理异构数据时非常常见,提供了一种类型安全的变通方案。

  • 底层数据操作/类型转换(通常不推荐,但仍存在于遗留代码): 联合体有时被用来“欺骗”编译器,将一块内存区域按不同的类型解释,从而实现某些底层操作。例如,将

    float
    的位模式作为
    unsigned int
    来访问,以检查其内部表示。

    union FloatToInt {
        float f;
        unsigned int i;
    };
    
    FloatToInt converter;
    converter.f = 3.14f;
    // 现在 converter.i 包含了 3.14f 的原始位模式
    // 注意:这种做法在C++中严格来说是类型双关 (type punning),
    // 除了C++20引入的union成员访问规则外,通常会导致未定义行为 (UB)。
    // 推荐的现代C++做法是使用 memcpy 或 C++20的 std::bit_cast 来进行这种位模式转换,
    // 以确保行为是明确和可移植的。

    我个人在维护一些老代码时,确实见过这种用法,虽然现在看来有些“野蛮”,但在那个年代,它提供了一种绕过类型系统的直接访问方式。不过,现代C++已经提供了更安全、更明确的机制来处理这些需求,因此在新的代码中应尽量避免这种直接的联合体类型双关。

热门AI工具

更多
火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2911

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

534

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

502

2026.02.12

css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

6467

2024.04.28

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

744

2025.10.23

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

4654

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

4811

2025.07.04

c语言union的用法
c语言union的用法

c语言union的用法是一种特殊的数据类型,它允许在相同的内存位置存储不同的数据类型,union的使用可以帮助我们节省内存空间,并且可以方便地在不同的数据类型之间进行转换。使用union时需要注意对应的成员是有效的,并且只能同时访问一个成员。本专题为大家提供union相关的文章、下载、课程内容,供大家免费下载体验。

689

2023.09.27

OpenJDK JVM参数怎么调优
OpenJDK JVM参数怎么调优

Java应用运行缓慢,如何调整JVM参数?本专题介绍OpenJDK JVM性能调优的基本流程,涵盖性能指标确认、运行数据采集、内存配置和垃圾回收分析,帮助你先定位瓶颈,再通过对照测试验证效果,避免直接套用参数而影响应用稳定性。

20

2026.10.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn