求知 文章 文库 Lib 视频 iProcess 课程 角色 咨询 工具 讲座 Modeler   Code  
会员   
要资料
 
追随技术信仰

随时听讲座
每天看新闻
 

C语言教程
C语言历史
C语言特点
C语言VS开发环境安装
C语言第一个程序
C语言程序执行流程
C语言printf()和scanf()函数
C语言变量
C语言数据类型
C语言关键字
C语言运算符
C语言注释
C语言转义序列
C语言常量
C语言控制语句
C语言if-else语句
C语言switch语句
C语言循环
C语言do-while循环
C语言while循环
C语言for循环
C语言break语句
C语言continue语句
C语言goto语句
C语言类型转换
C语言函数
C语言函数
C语言通过值和引用函数
C语言递归
C语言存储分类
C语言数组
C语言数组
C语言二维数组
C语言将数组传递给函数
C语言指针
C语言指针
C语言指针的指针
C语言指针算术运算
C语言字符串
C语言字符串
C语言gets()和puts()函数
C语言字符串函数
C语言strlen()函数
C语言strcpy()函数
C语言strcat()函数
C语言strcmp()函数
C语言strrev()函数
C语言strlwr()函数
C语言strupr()函数
结构联合体
C语言结构体
C语言结构体数组
C语言结构体嵌套
C语言联合体
文件处理
C语言文件处理
C语言fprintf()和fscanf()函数
C语言fputc()和fgetc()函数
C语言fputs()和fgets()函数
C语言fseek()函数
C语言rewind()函数
C语言ftell()函数
预处理器
C语言预处理器指令
C语言宏
C语言#include指令
C语言#define指令
C语言#undef指令
C语言#ifdef指令
C语言#ifndef指令
C语言#if指令
C语言#error指令
C语言#pragma指令
其它杂项
C语言数学函数
C语言命令行参数
 
 

C语言联合体
97 次浏览
1次  
 捐助

结构体一样,联合体(Union)在C语言中是一个用户定义的数据类型,用于保存不同类型的元素。

但它并不占所有成员的内存总和。它只占最大成员的内存,它分享最大成员的内存。

联合体优点

它占用较少的内存,因为它只占最大的成员的内存量。

联合体缺点

它将数据存储在一个成员中。

定义联合体

union关键字用于定义联合体。下面我们来看看如何在C语言中定义联合体的语法 -

union union_name
{
data_type member1;
data_type member2;
.
.
data_type memeberN;
};

 

我们来看看在C语言中定义员工联合体的例子。如下代码 -

union employee
{ int id;
char name[50];
float salary;
};

注:除了union关键字,其它均与结构体一样。

联合体的例子

我们来看看一个简单的C语言联合示例。创建一个源文件:union-example.c,其代码实现如下 -

#include <stdio.h>
#include <string.h>
union employee
{
int id;
char name[150];
}e1; //declaring e1 variable for union
int main()
{
//store first employee information
e1.id = 1010;
strcpy(e1.name, "Maxsu");//copying string into char array
//printing first employee information
printf("employee 1 id : %d, address: %u\n", e1.id, &e1.id);
printf("employee 1 name : %s, address: %u\n", e1.name, &e1.name);
e1.id = 1010;
printf("employee 1 id : %d, address: %u\n", e1.id, &e1.id);
printf("employee 1 name : %s, address: %u\n", e1.name, &e1.name);
return 0;
}

执行上面示例代码,得到以下结果 -

employee 1 id : 1937269069, address: 16819328
employee 1 name : Maxsu, address: 16819328
employee 1 id : 1010, address: 16819328
employee 1 name : ?, address: 16819328

如上输出结果中可以看到,id字段的值是一个垃圾值,因为name具有大的内存大小。所以只有name才具有实际值。

联合体完全就是共用一个内存首地址,并且各种变量名都可以同时使用,操作也是共同生效。如此多的访问内存手段,确实好用,不过这些“手段”之间却没法互相屏蔽——就好像数组+下标和指针+偏移一样。

由于联合体中的所有成员是共享一段内存的,因此每个成员的存放首地址相对于于联合体变量的基地址的偏移量为0,即所有成员的首地址都是一样的。为了使得所有成员能够共享一段内存,因此该空间必须足够容纳这些成员中最宽的成员。对于这句“对齐方式要适合其中所有的成员”是指其必须符合所有成员的自身对齐方式。

下面举例说明:

union U
{
char s[9];
int n;
double d;
};

 

 

s占9字节,n占4字节,d占8字节,因此其至少需9字节的空间。然而其实际大小并不是9,用运算符sizeof测试其大小为16.这是因为这里存在字节对齐的问题,9既不能被4整除,也不能被8整除。因此补充字节到16,这样就符合所有成员的自身对齐了。从这里可以看出联合体所占的空间不仅取决于最宽成员,还跟所有成员有关系,即其大小必须满足两个条件:1)大小足够容纳最宽的成员;2)大小能被其包含的所有基本数据类型的大小所整除。

测试程序,创建一个源文件:union-test.c,其代码实现如下 -

#include <stdio.h>
#include <string.h>
union U1
{
char s[9];
int n;
double d;
}u1;
union U2
{
char s[5];
int n;
double d;
}u2;
int main()
{
printf("%d\n", sizeof(u1));
printf("%d\n", sizeof(u2));
printf("0x%x\n", &u1);
printf("0x%x\n", &u1.s);
printf("0x%x\n", &u1.n);
printf("0x%x\n", &u1.d);
u1.n = 1;
printf("%d\n", u1.s[0]);
printf("%lf\n", u1.d);
unsigned char *p = (unsigned char *)&u1;
printf("%d\n", *p);
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 2));
printf("%d\n", *(p + 3));
printf("%d\n", *(p + 4));
printf("%d\n", *(p + 5));
printf("%d\n", *(p + 6));
printf("%d\n", *(p + 7));
return 0;
}

执行上面测试代码,得到以下结果 -

16
8
0xeca5a0
0xeca5a0
0xeca5a0
0xeca5a0
1
0.000000
1
0
0
0
0
0
0
0

 

 


您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码: 验证码,看不清楚?请点击刷新验证码 必填



97 次浏览
1次
 捐助
 

每天2个文档/视频
扫描微信二维码订阅
订阅技术月刊
获得每月300个技术资源
 
 

关于我们 | 联系我们 | 京ICP备10020922号 京公海网安备110108001071号