学而时习之:C++中的联合体

40 阅读3分钟

C++ 联合体

在 C++ 中,联合体是一种用户自定义的数据类型,可以容纳不同数据类型的成员。

与结构体不同,联合体的所有成员都存储在相同的内存位置。 由于所有成员共享同一内存,更改一个成员的值会覆盖其他成员的值。 联合体的大小始终等于联合体中最大成员的大小。所有较小尺寸的元素都可以在同一空间存储数据而不会发生溢出。让我们看一个代码示例:

#include <iostream>
using namespace std;

union A {
    int x;
    char y;
};

union B {
    int arr[10];
    char y;
};

int main()
{
    // 使用 sizeof() 运算符计算大小
    cout << "Sizeof A: " << sizeof(A) << endl;
    cout << "Sizeof B: " << sizeof(B) << endl;

    return 0;
}
Sizeof A: 4
Sizeof B: 40

上面的联合体内存可以可视化为如图所示。

image.png image.png

1. 联合体声明

联合体的声明方式与结构体类似。提供联合体的名称并定义其成员变量:

union union_Name {
    type1 member1;
    type2 member2;
    ..
};

联合体声明后,可以像下面这样创建联合体变量:

union_name variable_name;

我们也可以在声明联合体时同时声明变量:

union union_Name {
    type1 member1;
    type2 member2;
    .
    .
}variable_name;
#include <iostream>
using namespace std;

// 定义一个包含不同数据类型的联合体
union Student {
    int rollNo;
    float height;
    char firstLetter;
};

int main(){
    // 声明一个联合体变量
    Student data;

    data.rollNo = 21;
    cout << data.rollNo << endl;

    data.height = 5.2;
    cout << data.height << endl;

    data.firstLetter = 'N';
    cout << data.firstLetter << endl;

    return 0;
}
21
5.2
N

2.嵌套联合体

联合体可以定义在结构体、类或另一个联合体内部,称为嵌套联合体。这种方法有助于高效地组织和访问相关数据,同时在联合体的成员之间共享内存。

语法:

union name1 {

    // name1 的数据成员

    union name2 {

        // name2 的数据成员

    } inner;
};

使用点(.)运算符访问联合体成员:

name1 obj;
obj.inner.member; 

示例:

#include <iostream>
using namespace std;

// 定义一个包含嵌套联合体的结构体
struct Employee
{
    char name[50];
    int id;

    // 嵌套联合体
    union Pay {
        float hourlyRate;
        float salary;
    } payment; 
};

int main()
{
    Employee e1; 
    e1.id = 101;

    // 使用点运算符访问嵌套联合体成员
    e1.payment.hourlyRate = 300.0;

    cout << "Employee ID: " << e1.id << "\n";
    cout << "Hourly Rate: Rs " << e1.payment.hourlyRate << endl;

    // 如果需要,也可以赋值 salary
    e1.payment.salary = 50000.0;
    cout << "Salary: Rs " << e1.payment.salary << endl;

    return 0;
}
Employee ID: 101
Hourly Rate: Rs 300
Salary: Rs 50000

3.匿名联合体

匿名联合体是指那些在主函数内声明且没有名称的联合体。由于未定义联合体名称,我们可以直接访问其数据成员,因此成员必须声明为唯一的名称,以避免在当前作用域中产生歧义。

它们主要用于嵌套联合体中,可以像访问外部联合体/结构体的成员一样访问它们。

#include <iostream>
using namespace std;

struct Employee
{
    int id;

    // 匿名联合体
    union {
        float hourlyRate;
        float salary;
    };
};

int main()
{
    Employee e1; 
    e1.id = 101;

    // 访问匿名联合体成员
    e1.hourlyRate = 300;

    cout << "Employee ID: " << e1.id << "\n";
    cout << "Hourly Rate: Rs " << e1.hourlyRate << endl;

    // 同时只有一个成员是有效的
    e1.salary = 50000;
    cout << "Salary: Rs " << e1.salary << endl;

    return 0;
}
Employee ID: 101
Hourly Rate: Rs 300
Salary: Rs 50000

4.C++ 联合体的应用

  • 内存优化:用于提高内存效率,特别是在嵌入式系统或内存为关键资源的环境中。通过让不同数据类型共享同一块内存,相比结构体,它们减少了整体的内存占用。

  • 硬件寄存器映射:用于映射可能根据上下文有不同解释的硬件寄存器(例如,一个寄存器可以作为状态标志读取,或作为命令写入)。

  • 互斥数据表示:适用于表示可以是几种不同类型之一但绝不会同时存在的数据。例如,一个消息包可能包含一个整数 ID 或一个字符串消息,但不会两者兼有。