【C语言】共用体union:
- 也称联合体。同一个内存空间用于多个数据的存储。
- 同一时间只能存储一个成员数据。
- 使用内存覆盖技术。新的成员数据会覆盖原来的成员数据。
- 内存大小是最大的成员占用内存大小,且是最大对齐数的整数倍,若不足整数倍,将填充字节补齐。
1、定义共用体类型
- 关键字union。
- 包括共用体名、共用体成员。共用体成员由成员类型、成员变量名组成。
- 最后末尾的分号";"不能省略。
// 定义名为person的共用体,成员有字符串name,整数int,字符串指针job
union person
{
char name[20];
int age;
char *job;
};
2、共用体变量
(2-1)定义共用体变量
- 定义共用体类型后,定义共用体变量。可以定义一个或多个共用体变量。
union person
{
char name[20];
int age;
char *job;
};
union person p1; // 定义一个共用体变量
union person p1, p2, p3; // 定义多个共用体变量
- 定义共用体类型时,同时定义共用体变量。可以定义一个或多个共用体变量。
union person
{
char name[20];
int age;
char *job;
} p; // 定义共用体类型时,定义一个共用体变量
union person
{
char name[20];
int age;
char *job;
} p1, p2, p3; // 定义共用体类型时,定义多个共用体变量
(2-2)访问共用体成员
- 使用成员访问运算符(".")来访问共用体的成员。
#include <stdio.h>
#include <string.h>
union person
{
char name[20];
int age;
char *job;
};
int main(void)
{
union person p;
strcpy(p.name, "John"); // 成员name的值为John
p.age = 18; // 成员age的值覆盖原来成员name的值
p.job = "programer"; // 成员job的值覆盖原来成员age的值
printf("p.name is %s\n", p.name);
printf("p.age is %d\n", p.age);
printf("p.job is %s\n", p.job);
return 0;
}
// 结果:
p.name is // 数据被新数据覆盖,该数据已损坏
p.age is 4210688 // 数据被新数据覆盖,该数据已损坏
p.job is programer // 最后的数据占据内存
- 若是指针,使用箭头运算符("->")来访问共用体的成员。
#include <stdio.h>
#include <string.h>
union person
{
char name[20];
int age;
char *job;
};
int main(void)
{
union person *p, p1;
p = &p1; // 指针p指向共用体p1
strcpy(p->name, "John"); // 成员name的值为John
p->age = 18; // 成员age的值覆盖原来成员name的值
p->job = "programer"; // 成员job的值覆盖原来成员age的值
printf("p point to p1, name is %s\n", p->name);
printf("p point to p1, age is %d\n", p->age);
printf("p point to p1, job is %s\n", p->job);
return 0;
}
// 结果:
p point to p1, name is // 数据被新数据覆盖,该数据已损坏
p point to p1, age is 4210688 // 数据被新数据覆盖,该数据已损坏
p point to p1, job is programer // 最后的数据占据内存
3、共用体大小:
- 共用体的内存大小是最大的成员占用内存大小。
- 共用体的内存大小是最大对齐数的整数倍,若不足整数倍,将填充字节补齐。
#include <stdio.h>
union person
{
char name[20]; // 字符串name:20字节
int age; // 整数int:4字节
char *job; // 字符串指针job:8字节(64位的计算机)
};
int main(void)
{
union person p;
printf("p memory size is %d bytes\n", sizeof(p));
return 0;
}
// 结果:
p memory size is 24 bytes //最大成员内存大小为20,不足最大对齐数的整数倍,填充字节补齐
4、共用体作为结构体的成员
注:数组名就是内存地址(数组第一个元素的内存地址)。整数的内存地址需用&获取(&整数变量名)。
字符数组通常用于表示字符串。字符串名也是内存地址(字符串第一个元素的内存地址)。
#include <stdio.h>
#include <string.h>
struct person // 结构体
{
char name[20];
int age;
char job[16];
union // 共用体, language或者place,只能提供一个数据
{
char language[16];
char place[16];
}lp; // 共用体变量名lp
}p[2]; // 结构体数组p
int main(void)
{
// 根据用户输入,写入数据
for(int i = 0; i < 2; i++)
{
printf("[ Input ]name age job (NO.%d): ", i+1);
scanf("%s %d %s", p[i].name, &p[i].age, p[i].job);
// 如果job是programmer,则提供language,否则提供place
if(strcmp(p[i].job, "programmer") == 0)
{
printf("Input language: ");
scanf("%s", p[i].lp.language);
}
else
{
printf("Input place: ");
scanf("%s", p[i].lp.place);
}
}
// 输出数据
for(int i = 0; i < 2; i++)
{
if(strcmp(p[i].job, "programmer") == 0)
printf("%s, %d, %s, %s\n", p[i].name, p[i].age, p[i].job, p[i].lp.language);
else
printf("%s, %d, %s, %s\n", p[i].name, p[i].age, p[i].job, p[i].lp.place);
}
return 0;
}
// 结果:
[ Input ]name age job (NO.1): John 18 programmer 【输入:John 18 programmer】
Input language: C 【输入:C】
[ Input ]name age job (NO.2): Mark 25 teacher 【输入:Mark 25 teacher】
Input place: Beijing 【输入:Beijing】
John, 18, programmer, C
Mark, 25, teacher, Beijing
5、共用体与结构体的主要区别
共用体 | 结构体 |
---|---|
各成员在相同的内存位置 | 各成员在不同的内存位置 |
同一时间只能存储一个成员数据 | 同一时间可以存储多个不同类型的成员数据 |
新的成员数据会覆盖原来的成员数据 | 各成员的数据互不影响 |
内存大小 >= 最大的成员内存大小 | 内存大小 >= 各成员内存大小之和 |
关键字union | 关键字struct |