目录
C语言支持的自定义类型还剩下联合体和枚举没有介绍了,本篇将介绍这两个。
1 · 联合体
1 - 1 · 联合体类型的声明
联合体的关键字是 union
union Un
{
//联合体的声明
char c;
int i;
};
这就是联合体的声明,可以有不同类型的多个成员,那么此时这个联合体的大小是多少呢?
#include <stdio.h>
union Un
{
//联合体的声明
char c;
int i;
};
int main()
{
union Un un = { 0 };
printf("%zd\n", sizeof(un));
return 0;
}
运行一下试试:

char 类型的大小是1个字节,int 类型的大小是4个字节,这里我们就能看出这两个成员变量大概率是共用一片空间的。下面我们展开介绍联合体的特点,并测试一下。
1 - 2 · 联合体的特点
#include <stdio.h>
union Un
{
//联合体的声明
char c;
int i;
};
int main()
{
union Un un = { 0 };
printf("联合体的地址: %p\n", &un);
printf("成员变量c的地址:%p\n", &(un.c));
printf("成员变量i的地址:%p\n", &(un.i));
un.i = 0x11223344;
printf("i的值为:%x\n", un.i);
un.c = 0x55;
printf("i的值为:%x\n", un.i);
return 0;
}
运行一下:

便于理解,我们可以画个图:

所以在联合体中,所有成员变量共用同一块空间,从低地址开始共用,修改其中一个成员变量的值可能会影响其他成员变量,所以在使用联合体时最好只使用其中一个变量。因此,联合体的使用场景为 有一些东西,当使用其中一个的时候,就不用其他的,这样的话这些东西就可以放在联合体中。
1 - 3 · 相同成员的结构体和联合体对比
假设我们现在有一个和上面联合体相同成员变量的结构体:
struct S
{
char c;
int i;
};
我们照样画张图对比一下:

结构体中 i 和 c 分别有各自独立的空间,而联合体中 c 和 i 是共用同一块空间
1 - 4 · 联合体大小的计算
#include <stdio.h>
union Un
{
char c[5];
int i;
};
int main()
{
union Un u = { 0 };
printf("%zd\n", sizeof(u));
return 0;
}
运行一下:

char c[5] 是一个 char 类型的数组,大小为5,占5字节,但是由于是 char 类型,所以本身的对齐数为1,VS2022 中默认对齐数是8,所以 c成员变量的对齐数是 1,i 占4字节,对齐数是4。
所以此时最大成员大小是5,但是对齐数是4,所以联合体大小要对齐到 8 。
1 - 5 · 关于联合体的例子
struct gift_list
{
//公共属性
int stock_number;//库存量
double price; //定价
int item_type;//商品类型
//特殊属性
char title[20];//书名
char author[20];//作者
int num_pages;//⻚数
char design[30];//设计
int colors;//颜⾊
int sizes;//尺⼨
};
1 - 6 · 使用联合体判断大小端
#include <stdio.h>
union Un
{
int i;
char c;
};
int Check()
{
union Un u = { 0 };
u.i = 1;
return u.c;
}
int main()
{
int ret = Check();
if (ret == 1)
{
printf("是小端\n");
}
else
{
printf("是大端\n");
}
return 0;
}
将 i 赋值为1,其实也就是 0x00 00 00 01,如果是小端,那么低位数据放在低地址,而联合体是从低地址开始共用的,所以如果 c == 1 ,说明此时是小端,如果 c == 0 ,说明此时是大端。
2 · 枚举
2 - 1 · 枚举类型的声明
enum Day//星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
这里的 enum Day 就是枚举类型,大括号{ }中的内容是枚举类型的可能取值,也叫 枚举常量 。
每一个可能取值后面要跟逗号。
我们可以看一看:
int main()
{
printf("%d\n", Mon);
printf("%d\n", Tues);
printf("%d\n", Wed);
printf("%d\n", Thur);
return 0;
}
运行一下:
![]()
可以看到,这些枚举常量都是有值的,默认从0开始,以此递增1。
既然是枚举常量,那么是不可以给枚举常量赋值的 如果想要改变枚举常量的值,需要在声明时赋初值:
#include <stdio.h>
enum Day//星期
{
Mon,
Tues = 3,
Wed,
Thur = 6,
Fri,
Sat,
Sun
};
int main()
{
printf("%d\n", Mon);
printf("%d\n", Tues);
printf("%d\n", Wed);
printf("%d\n", Thur);
printf("%d\n", Fri);
return 0;
}
运行一下:
![]()
可以看到,给一个枚举常量赋初始值,会影响后续的枚举常量的值。
2 - 2 · 枚举类型的优点
如果想要定义一个常量,我们在扫雷那一篇中是使用过 #define 的,那么枚举有什么优点呢:
void Menu()
{
printf("*****************\n");
printf("* 1:Add 2:Sub *\n");
printf("* 3:Mul 4:Div *\n");
printf("* 0:exit *\n");
printf("*****************\n");
}
switch (input)
{
case 1:
...
break;
case 2:
...
break;
case 3:
...
break;
case 4:
...
break;
case 0:
printf("成功退出\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
那么我们使用枚举,就可以这样写:
enum Option
{
EXIT,
ADD,
SUB,
MUL,
DIV
};
void Menu()
{
printf("*****************\n");
printf("* 1:Add 2:Sub *\n");
printf("* 3:Mul 4:Div *\n");
printf("* 0:exit *\n");
printf("*****************\n");
}
switch (input)
{
case ADD:
...
break;
case SUB:
...
break;
case MUL:
...
break;
case DIV:
...
break;
case EXIT:
printf("成功退出\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
相当于给常量值起了个名字,这样代码的可读性就提高了。
2 - 3 · 枚举类型的使用
简单来说就是声明一个枚举类型,然后定义枚举变量,将枚举常数赋值给枚举变量,如下:
enum Color//颜⾊
{
RED=1,
GREEN=2,
BLUE=4
};
enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值
总结
以上简单介绍了联合体和枚举相关内容,关于C语言的其余内容,请期待后续更新
以上内容如有错误或不准确之处,欢迎指出,或者你有更好的想法,也欢迎交流。
1622

被折叠的 条评论
为什么被折叠?



