目录
1 联合体类型的声明
2 联合体的特点
3 联合体的大小计算
4 枚举类型类型的声明
5 枚举的优点
联合体,顾名思义,是多个对象连在一起的,即联合体的成员都是共用空间的,所以联合体也叫做共用体,既然是共用一块空间,那么改变其中一个成员的值的时候,其他对象的值也会随着改变。
联合体用到的关键字是union。
先介绍第一个特性,共用一块空间,
union un
{
char a;
int b;
};
int main()
{
union un tem;
printf("%zd\n", sizeof(tem));
return 0;
}
联合体里面有一个字符类型,一个整型,整型占4个字节,字符占1个字节,所以会占4个字节。
即编译器只会给占内存最大的成员分配空间。
介绍第二种特性,共用一块空间。
union un
{
char a;
int b;
};
int main()
{
union un tem;
printf("%zd\n", sizeof(tem));
tem.b = 0x11223344;
printf("%x %x", tem.a, tem.b);
return 0;
}
因为vs是小端存储,所以存的16进制的11223344,所以存的顺序是44332211,那么a的值就是44,b的值就是11223344。
前面提到的可以用联合体判断机器是大端机器还是小端机器,就是完美利用了联合体的特点,
union un
{
char a;
int b;
};
int main()
{
union un tem;
tem.b = 0x11223344;
if (tem.a == 11)
{
printf("大端");
}
else
{
printf("小端");
}
return 0;
}
在写联合体的时候,需要注意花括号后面要有分号,定义联合体变量的时候,是需要写union un的,当然,可以直接在花括号后面写,那种写法是表示定义,如下:
union un
{
char a;
int b;
}tem1,tem2;
联合的成员是共⽤同⼀块内存空间的,这样⼀个联合变量的⼤⼩,⾄少是最⼤成员的⼤⼩(因为联合 ⾄少得有能⼒保存最⼤的那个成员)。
先看一段代码
union Un
{
char c;
int i;
};
int main()
{
union Un un = { 0 };
printf("%p\n", &(un.i));
printf("%p\n", &(un.c));
printf("%p\n", &un);
return 0;
}
问打印的结果都是一样的吗?
没错是的,这就是说明联合体的存放元素的时候都是从同一块空间开始存的。
因为空间共用,所以我们要修改前文的11223344中的44也是可以的,这里请自行实验咯。
这里稍微引入一点结构体的知识,我们比较一下在相同的成员情况下,结构体和联合体占用的内存多少。
union Un
{
int a;
char c;
int i;
}un;
struct St
{
int a;
char c;
int i;
}st;
int main()
{
printf("%zd\n", sizeof(un));
printf("%zd\n", sizeof(st));
return 0;
}
可以看到,成员有两个char,一个int类型的,所以联合体的大小应该是4,那么结构体的大小是?
是12?!对,确实是12,至于为什么,就下一篇再介绍了,这里涉及到的知识是内存对齐。
联合体的大小就一定是最大成员的大小吗?举个例子。
union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
};
int main()
{
printf("%zd\n", sizeof(union Un1));
printf("%zd\n", sizeof(union Un2));
return 0;
}
按刚才的来讲,Un1的大小应该是5,Un2的大小应该是14,让我们来揭晓谜底。
结果是8 16,这是因为最大成员的大小不是最大对齐数的整数倍的时候,系统就会浪费空间去凑到最大对齐数的整数倍,且听下回分解。
现实生活中比如星期1到星期7,性别,三原色,我们都是可以一一列举的,这就是枚举,将有限个数的元素一一列举出来。
枚举用到的关键字是enum,里面的成员叫做枚举常量,如下:
enum Color
{
Red,
Blue,
yellow
};
注意格式,枚举变量中间是用逗号进行隔开的,且最后是没有分号的,但是花括号的后面依旧是有分号的。
这是枚举的声明,那枚举常量有没有值呢?
答案是有的,并且看来是层层递增的,那么我们如果附上初值呢?
enum Color
{
Red = 1,
Blue = 3,
yellow
};
int main()
{
printf("%d ", Red);
printf("%d ", Blue);
printf("%d ", yellow);
return 0;
}
所以可以得出结论,枚举常量的值是递增的,修改之后也是递增的,且默认从0开始递增。
既然枚举常量是整型,是常量,我们可以应用到switch语句里面吗?
enum Color
{
Red,
Blue,
yellow
};
int main()
{
switch (Blue)
{
case 0:
printf("0");
break;
case 1:
printf("1");
break;
case 2:
printf("2");
break;
default:
break;
}
return 0;
}
当然是可以的,最后的结果就是1。
枚举常量也是可以用于给枚举常量赋值的。
enum Color clr = Blue;
像这样,但是在C语言里面是可以用整数给枚举常量赋值的,c++里面是不可以的,因为c++的类型检查比较严格,会认为这是两种不同的类型不能进行赋值。
枚举的优点(和define相比):
1. 增加代码的可读性和可维护性
2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。
3. 便于调试,预处理阶段会删除 #define 定义的符号
4. 使⽤⽅便,⼀次可以定义多个常量
5. 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤
感谢阅读!