C —— 联合体

在进行某些算法的C语言编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构,简称共用体,也叫联合体。
—— 摘自百度百科

定义联合体与使用

联合体是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。程序中可以定义带有多个成员的联合体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。用到的关键字是 union,其格式如下:

union 联合体名称 {
	member-list
}

实例代码如下:

#include<stdio.h>

union Person {
	char name[50];
	unsigned int age;
	double weight;
};

int main() {

	union Person person;
	strcpy(person.name, "tom");
	person.age = 27;
	person.weight = 46.9;
	printf("person.name = %s, person.age = %d, person.weight = %f\n", person.name, person.age, person.weight);
	
	return 0;
}

执行结果:

person.name = 33333sG@諏鱱AQ, person.age = 858993459, person.weight = 46.900000

可以看到,只有成员 weight 的值是被正确的输出,原因是这三个成员变量在储值的时候占用的是同一个内存空间,相当于这三个成员指向的是同一块内存空间,当 weight 被赋值之后,其他的成员的值就被损坏。使用 & 可以查看各个成员指向的地址值:

union Person up;
printf("&up=%p, &up.name=%p, &up.age=%p, &up.weight=%p\n", &up, &up.name, &up.age, &up.weight);

执行结果如下:

&up=0022FF08, &up.name=0022FF08, &up.age=0022FF08, &up.weight=0022FF08

如果需要在联合体变量被声明的时候赋予初始值的话,因为它们共用同一个内存空间,故而,不需要将每个值都赋值,而且编译器只会接收第一个值作为有效值填入合适的成员中。例如:

#include<stdio.h>

union Person {
	char name[50];
	unsigned int age;
	double weight;
};

int main() {


	union Person up1 = {"Tom", 12, 4.6};
	union Person up2 = {12};
	union Person up3 = {4.6};
	union Person up4 = {"Tom"};
	printf("name=%s, age=%d, weight=%f\n", up1.name, up1.age, up1.weight);
	printf("name=%s, age=%d, weight=%f\n", up2.name, up2.age, up2.weight);
	printf("name=%s, age=%d, weight=%f\n", up3.name, up3.age, up3.weight);
	printf("name=%s, age=%d, weight=%f\n", up4.name, up4.age, up4.weight);
	
	return 0;
}

该源程序在编译的时候给出警告和提示:

warning: excess elements in union initializer
  union Person up1 = {"Tom", 12, 4.6};
                             ^~
note: (near initialization for 'up1')
warning: excess elements in union initializer
  union Person up1 = {"Tom", 12, 4.6};
                                 ^~~
note: (near initialization for 'up1')

执行结果变成了:

name=Tom, age=7171924, weight=0.000000
name=, age=12, weight=0.000000
name=, age=4, weight=0.000000
name=Tom, age=7171924, weight=0.000000

从本例中可以看到,联合体 up1 和 up4 接受的值是字符串 Tom,联合体 up2 接受的值是 12,联合体 up3 将传递的小数直接转换为了整型赋值给了 age 成员,接受的值是 4。故而,在给联合体变量声明的时候不需要为每个成员变量赋值,只需要赋予一个合适类型的值即可。

联合体作为参数

将联合体作为参数传递到函数中的操作方式与结构体一样。但是因为共享内存的原因,在函数内,仅接受一个有效值。代码如下:

#include<stdio.h>
#include<string.h>

union Person {
	char name[50];
	unsigned int age;
	double weight;
};

void printPerson(union Person p) {
	printf("Person{name:%s, age:%d, weight:%f}", p.name, p.age, p.weight);
}

int main() {
	union Person up = {12};
	printPerson(up);
	return 0;
}

执行结果:

Person{name:, age:12, weight:0.000000}

指向联合体的指针

指向联合体的指针在使用上与结构体一致,主要使用的运算符是 ->。具体代码如下:

#include<stdio.h>
#include<string.h>

union Person {
	char name[50];
	unsigned int age;
	double weight;
};

void printPerson(union Person *p) {
	printf("Person{name:%s, age:%d, weight:%f}", p->name, p->age, p->weight);
}

int main() {
	union Person up = {12};
	union Person *p = &up;
	printPerson(p);	
	return 0;
}

执行结果:

Person{name:, age:12, weight:0.000000}
### C语言联合体的概念及用法 #### 联合体的基本概念 联合体(`union`)是一种特殊的数据类型,在C语言中允许在同一内存位置存储不同的数据类型。它类似于结构体,但是所有的成员共享同一块内存空间。这意味着联合体的大小由占用最大空间的那个成员决定。 联合体的关键特性在于它的所有成员共用一块内存区域,因此在任何时刻只有一个成员能够保存有效的值[^1]。 #### 定义联合体 定义联合体的方式与定义结构体相似,只是关键字不同。以下是联合体的定义方式: ```c union 名称 { 类型 成员名; }; ``` 例如: ```c union Un { char c; // 占用1字节 int i; // 占用4字节 }; ``` 在这个例子中,`Un` 是一个联合体类型,其中 `c` 和 `i` 共享相同的内存位置。联合体的实际大小取决于最大的成员,即此例中的 `int` 的大小为 4 字节。 #### 创建联合体变量并初始化 创建联合体变量的方法也与结构体类似。可以通过以下方式进行初始化: ```c union Un u = {0}; // 初始化第一个成员 printf("%d\n", sizeof(u)); // 输出联合体的大小 ``` 上述代码展示了如何通过初始化第一个成员来设置整个联合体的内容,并且使用 `sizeof()` 函数获取联合体的总大小。 #### 访问联合体成员 访问联合体成员的方式与结构体相同,使用点运算符 (`.`) 来访问成员。需要注意的是,修改任何一个成员都会影响其他成员的值,因为它们共享同一个内存地址。 示例代码如下: ```c #include<stdio.h> union u{ int i; double d; // 这个 union 有 8 字节大小 }; main(){ union u uu; uu.i = 10; printf("%d\n",uu.i); char * c; c = (char *)&uu; // 把 union 的首地址赋值、强转成 char 类型 c[0] = 'a'; c[1] = 'b'; c[2] = 'c'; c[3] = '\0'; c[4] = 'd'; c[5] = 'e'; printf("%s\n",c); // 利用结束符 '\0' 打印字符串 "abc" printf("%c %c %c %c %c %c\n",c[0],c[1],c[2],c[3],c[4],c[5]); } ``` 这段代码演示了如何通过指针操作联合体内存,并展示了一个有趣的场景——将联合体视为连续的字节数组进行处理[^2]。 #### 应用实例:判断内存存储顺序 联合体的一个典型应用是用来检测系统的内存存储模式(大端或小端)。下面是一个具体的实现案例: ```c union U { char c; int i; }u; int main() { u.i = 1; // 设置整数值为 1 if (u.c == 1) { printf("小端"); } else { printf("大端"); } } ``` 在此程序中,如果最低位位于低地址处,则系统采用小端存储;反之则为大端存储[^4]。 #### 联合体与其他数据类型的对比 虽然联合体看起来像数组或者结构体的一部分,但它具有独特的性质。不同于数组和结构体会分配独立的空间给每一个元素/字段,而联合体只保留足够的空间容纳最宽广的单个成员即可[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值