【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的值为Johnp.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指向共用体p1strcpy(p->name, "John"); // 成员name的值为Johnp->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]; // 结构体数组pint 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,否则提供placeif(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);elseprintf("%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 |