Skip to main content

C 枚举、联合体

C 枚举

1. 基本概念

枚举是 C 语言中的一种基本数据类型,它可以让数据更加简洁明了。

enum 枚举名 {枚举元素1, 枚举元素2, 枚举元素3, ...}

当然也可以采用宏定义的方式来定义常量,比如定义一个星期的天数:

#define MON  1 
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7

这样会显得代码量很多,用枚举的方式就会是这样,所以枚举更简洁一点。

enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};

注意:第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。在上面这个实例中把第一个枚举成员的值定义为 1,第二个就为 2,以此类推。

可以在定义枚举类型时改变枚举元素的值:

enum season {spring, summer=3, autumn, winter};

没有指定值的枚举元素,其值为前一元素加 1。也就说 spring 的值为 0,summer 的值为 3,autumn 的值为 4,winter 的值为 5

2. 枚举变量的定义

前面我们只是声明了枚举类型,接下来我们看看如何定义枚举变量。

我们可以通过以下三种方式来定义枚举变量

  • 先定义枚举类型,再定义枚举变量
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;
  • 定义枚举类型的同时定义枚举变量
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
  • 省略枚举名称,直接定义枚举变量
enum
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;

C 联合体

1. 基本概念

联合体又叫共用体,它是一种特殊的数据类型,虽然和结构体很相似,但它们有本质的区别:结构体的各个成员是各自独立的,它们的内存位置是不同的,但联合体却是在相同的内存位置存储不同的数据类型。

2. 定义联合体

联合体的定义跟结构体很相似。

union tag { 
member-list
member-list
member-list
...
} variable-list ;
  • tag 是联合体标签。
  • member-list 是标准的变量定义,可以说有效的数据类型定义。
  • variable-list 联合体变量,定义在联合体的末尾,最后一个分号之前,可以指定一个或多个变量结构。
  • 在一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个。

union tag 是可选的,每个 member definition 是标准的变量定义,比如 int i; 或者 float f; 或者其他有效的变量定义。在联合体定义的末尾,最后一个分号之前,您可以指定一个或多个联合体变量,这是可选的。

定义一个名为 Data 的共用体类型,有三个成员 x、y 和 z:

union Data 
{
int x;
char y;
double z;
} data;

现在,Data 类型的变量可以存储一个整数、一个浮点数,或者一个字符。这意味着一个变量(相同的内存位置)可以存储多个多种类型的数据。

3. 初始化及访问联合体成员

  • 初始化联合体成员
 // 普通初始化:第一个成员有效(即只有100是有效的,其余成员会被覆盖)
union Data at = {100, 'k', 3.14};

// 指定成员初始化:最后一个成员有效(即只有3.14是有效的,其余成员会被覆盖)
union Data at = {
.x = 100,
.y = 'k',
.z = 3.14,
}
  • 访问联合体成员

访问共用体的成员,跟结构体一样需要使用成员访问运算符(.)。但由于联合体特殊的存储特性,不管怎么初始化和赋值,最终都是只有一个成员是有效的。

at.x = 100;
at.y = 'k';
at.z = 3.14; // 只有最后一个赋值的成员有效

printf("%d\n", at.x);
printf("%c\n", at.y);
printf("%lf\n", at.z);
  • 联合体指针
union Data *p = &at;

p->x = 100;
p->y = 'k';
p->z = 3.14; // 只有最后一个赋值的成员有效

printf("%d\n", p->x);
printf("%c\n", p->y);

4. 联合体的使用

联合体很少去单独去使用,常以结构体成员的形式存在,用来表达某种互斥的属性。

union Data 
{
int x;
char y;
double z;
};

struct node
{
int a;
char b;
double c;
union Date at; // at内有三种互斥的属性,非此即彼
};

int main(int argc, char *argv[])
{
struct node n;
n.at.x = 100;
}