联合体
联合体(union)是一种特殊的数据类型,可以在同一内存空间中存储不同类型的数据。
联合体和结构体(struct)类似,但不同之处在于结构体的各个成员会分别占用内存空间,而联合体的各个成员共享同一内存空间。鉴于这个特性,联合体也叫做共用体。
联合体的声明
代码语言:javascript复制union union_name
{
data_type member1;
data_type member2;
// 可以有多个成员
};
联合体的大小
因为共享同一内存空间,那么为了有足够的空间来装下所有的成员,那么联合体大小必须要大于最大成员的大小。
但是需要注意的是,当最大成员大小不是最大对齐数的整数倍的时候,那么此时联合体的大小为了内存对齐要扩大为最大对齐数的整数倍
举例:
代码语言:javascript复制#include <stdio.h>
union Un1
{
char c[5];
int i;
};
int main()
{
//求下⾯输出的结果
printf("%dn", sizeof(union Un1));
return 0;
}
输出结果应该是
代码语言:javascript复制8;
因为int类型占四个字节,而c数组占五个字节,那么鉴于5不是最大对齐数的整数倍,所以系统就会自动默认该联合体的大小为8个字节。
联合体的用处
鉴于它共享空间的特性,那么就可以达到节省空间的目的。
例如:
现在商店需要知道商品的一些信息。
商品1:单价,数量,质量
商品2:单价,数量,销售量
商品3:单价,数量,批发价
三种商品共同的属性是单价和数量,这些属性实际上可以共享同一块空间,没有必要再分为三块而浪费两块大小的空间。其他不同的属性再独自占各自的空间。
联合体的实例
要求写一个程序,用联合体的知识来判断机器为大端还是小端
代码语言:javascript复制#include <stdio.h>
union Endian
{
int num;
char bytes[sizeof(int)];
};
int main()
{
union Endian e;
e.num = 1;
if (e.bytes[0] == 1)
{
printf("当前机器为小端n");
}
else
{
printf("当前机器为大端n");
}
return 0;
}
在这个程序中,定义了一个联合体 Endian
,其中包含一个整型成员 num
和一个字符数组成员 bytes
,大小为整型的大小。
在 main
函数中,将整型变量 num
赋值为1,然后通过字符数组 bytes
的第一个元素来判断当前机器是大端还是小端。
如果 bytes[0]
的值为1,则表示当前机器为小端;如果 bytes[0]
的值为0,则表示当前机器为大端。最后根据判断结果输出相应的信息。
枚举
枚举顾名思义,就是将情况一一列举。
而枚举实际上是根据某个事物包括的情况来列举的。例如一周是有周一到周日七种情况,而身份是有父亲儿子等等多种情况。
枚举要做的就是把情况都列出来。
代码语言:javascript复制enum enum_name
{
constant1,
constant2,
constant3,
// 可以有多个常量
};
需要注意的是,枚举中的可能取值都是常量,它们可以被初始化,但是是不可变的。
代码语言:javascript复制enum Weekday
{
MON = 1,
TUE,
WED,
THU,
FRI,
SAT,
SUN
};
枚举的作用
枚举类型可以用于定义变量、函数参数、函数返回值等,以表示某种状态或选项。例如:
代码语言:javascript复制enum Weekday today = TUE;
枚举类型还可以与 switch
语句结合使用,方便对不同的枚举值进行处理。例如:
switch (today)
{
case MON:
printf("Today is Mondayn");
break;
case TUE:
printf("Today is Tuesdayn");
break;
// 其他枚举值的处理
}
枚举的优点
- 增加代码可读性:通过使用枚举,可以用有意义的名称来表示一组相关的常量,使代码更易于理解和阅读。
- 提高代码可维护性:枚举可以集中定义相关的常量,当需要修改常量值时,只需修改枚举定义即可,而无需在代码中逐个修改每个常量。
- 相较于#define:枚举可以进行类型检查,更具有严谨性
- 类型安全,使用安全:枚举类型是一种类型安全的数据类型,编译器会检查枚举值的合法性,防止使用未定义的值。并且一次可以定义多个常量
- 提高代码的可移植性:枚举类型可以在不同平台上保持一致,因为枚举值的值是由编译器自动生成的。