您的位置:

结构体(Struct)与联合体(Union)的区别

一、定义和用法

结构体(Struct)和联合体(Union)是C语言中同属于复合数据类型的一种类型,两者都可以封装多个不同类型的数据,但是却有着显著的不同之处。

1. 结构体的定义和用法

结构体是一种用户定义的数据类型,它可以用来封装多个不同类型的数据。通常情况下,结构体成员被设计为具有不同的数据类型。结构体通常被用来代表一个数据对象,例如汽车、学生、员工等等。C语言中结构体由多个成员组成,每个成员可以是不同类型的数据。


struct car {
    char brand[20];
    char model[20];
    int year;
    float price;
};

上述代码定义了一个名为car的结构体,它包含四个成员,分别是char类型的brand和model、int类型的year和float类型的price。我们可以使用结构体来表示一辆汽车。

2. 联合体的定义和用法

联合体是一种特殊的结构体,它的所有成员共享同一段内存。联合体的所有成员使用同一份内存空间,所以修改其中某一个成员的值,会影响到另一个成员的值。联合体通常被用来节省内存,例如有一些数据只用到其中一个成员。


union data {
    int integer;
    float decimal;
};

上述代码定义了一个名为data的联合体,它包含了两个成员,一个是int类型的integer,另一个是float类型的decimal,它们占据同一段内存空间。我们可以使用联合体来表示一个数据,可以是一个整数或者是一个浮点数。

二、内存布局

结构体和联合体的内存布局也有着非常大的区别。

1. 结构体的内存布局

结构体的内存布局是将每个成员单独分配内存,并依次排列。每个成员在内存中的地址都是连续的,各成员之间在内存中没有任何关联。


struct car {
    char brand[20];
    char model[20];
    int year;
    float price;
};

struct car mycar;

上述代码定义了一个名为mycar的结构体变量。

内存图:


    0          20              40          44
 +----------+----------------+----------+----------+
 |   brand  |     model      |   year   |   price   |
 +----------+----------------+----------+----------+
 |                                                       |
 mycar

在内存中,四个成员按照定义的顺序被依次排列。用sizeof运算符可以计算结构体的大小(单位为字节)。


printf("%zu", sizeof(mycar)); // 输出:44

2. 联合体的内存布局

联合体的内存布局只分配联合体中最大的成员所需要的内存空间,不管其他的成员的大小是多少。每个成员在内存中的地址都是相同的。


union data {
    int integer;
    float decimal;
};

union data mydata;

上述代码定义了一个名为mydata的联合体变量。

内存图:


   0-3    4-7
 +-------+
 |integer|   4 bytes
 +-------+
   OR
 +-------+
 |decimal|   4 bytes
 +-------+
 mydata

在内存中,union中仅分配了4个字节的空间,不管是integer还是decimal都使用这4个字节,因此,修改一个成员会影响到另外一个成员。


mydata.integer = 12;
printf("%d, %f", mydata.integer, mydata.decimal); // 输出:12, 0.000000

mydata.decimal = 23.45;
printf("%d, %f", mydata.integer, mydata.decimal); // 输出:1093507190, 23.450001

三、应用场景

1. 结构体的应用场景

结构体通常被用来封装多个相关类型的数据,使得这些数据可以统一管理,方便使用。例如,用结构体来表示一个学生信息。


struct student {
    char name[20];
    int age;
    char gender[6];
};

2. 联合体的应用场景

联合体通常被用来在一段内存空间中同时表示多个数据类型,这些数据类型在不同的时间和场合下只有一个会被使用。例如,用联合体来表示数据类型转换。


union data {
    int integer;
    float decimal;
};

void swap(union data *a, union data *b) {
    union data temp = *a;
    *a = *b;
    *b = temp;
}

union data d1, d2;
d1.integer = 12345;
d2.decimal = 67.89;

swap(&d1, &d2);

printf("%d, %f", d1.integer, d2.decimal); // 输出:1090873190, 12345.000000

四、小结

结构体和联合体是C语言中的两种复合数据类型,结构体将多个不同类型的成员按顺序排列在一起,并分配不同的内存空间;联合体将多个数据类型的成员共享同一段内存,以节省内存空间。两者在应用场景上也有所不同,需要根据实际需求选择使用。