浅谈C语言中的联合体

简介:

        联合体union

      当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union)。在C Programming Language 一书中对于联合体是这么描述的:

     1)联合体是一个结构;

     2)它的所有成员相对于基地址的偏移量都为0;

     3)此结构空间要大到足够容纳最"宽"的成员;

     4)其对齐方式要适合其中所有的成员;

下面解释这四条描述:

     由于联合体中的所有成员是共享一段内存的,因此每个成员的存放首地址相对于于联合体变量的基地址的偏移量为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)大小能被其包含的所有基本数据类型的大小所整除。

测试程序:

复制代码
/*测试联合体  2011.10.3*/

#include <iostream>
using namespace std;

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

union U2
{
char s[5];
int n;
double d;
};

int main(int argc, char *argv[])
{
U1 u1;
U2 u2;
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
0x22ff60
0x22ff60
0x22ff60
0x22ff60
1
0.000000
1
0
0
0
48
204
64
0
请按任意键继续. . .

对于sizeof(u1)=16。因为u1中s占9字节,n占4字节,d占8字节,因此至少需要9字节。其包含的基本数据类型为char,int,double分别占1,4,8字节,为了使u1所占空间的大小能被1,4,8整除,则需填充字节以到16,因此sizeof(u1)=16.

对于sizeof(u2)=8。因为u2中s占5字节,n占4字节,d占8字节,因此至少需要8字节。其包含的基本数据类型为char,int,double分别占1,4,8字节,为了使u2所占空间的大小能被1,4,8整除,不需填充字节,因为8本身就能满足要求。因此sizeof(u2)=8。

从打印出的每个成员的基地址可以看出,联合体中每个成员的基地址都相同,等于联合体变量的首地址。

对u1.n=1,将u1的n赋值为1后,则该段内存的前4个字节存储的数据为00000001 00000000 00000000 00000000

因此取s[0]的数据表示取第一个单元的数据,其整型值为1,所以打印出的结果为1.

至于打印出的d为0.000000愿意如下。由于已知该段内存前4字节的单元存储的数据为00000001 00000000 00000000 00000000,从上面打印结果48,204,64,0可以知道后面4个字节单元中的数据为00110000 11001100 01000000 00000000,因此其表示的二进 制浮点数为

00000000 01000000 11001100 00110000 00000000 00000000 00000000 00000001

对于double型数据,第63位0为符号位,62-52 00000000100为阶码,0000 11001100 00110000 00000000 00000000 00000000 00000001为尾数,根据其值知道尾数值约为0,而阶码为4-1023=-1019,因此其表示的浮点数为1.0*2^(-1019)=0.00000000000......,因此输出结果为0.000000。


本文转载自海 子博客园博客,原文链接:http://www.cnblogs.com/dolphin0520/archive/2011/10/03/2198493.html如需转载自行联系原作者


相关文章
|
1月前
|
Ubuntu 编译器 Linux
C语言中经典的结构体和联合体共用实例
C语言中经典的结构体和联合体共用实例
20 0
|
5月前
|
编译器 C语言 C++
C语言学习系列->联合体and枚举
C语言学习系列->联合体and枚举
38 0
|
6月前
|
存储 开发框架 .NET
【C语言】自定义类型:结构体,枚举,联合体
【C语言】自定义类型:结构体,枚举,联合体
34 0
【C语言】自定义类型:结构体,枚举,联合体
|
17天前
|
存储 搜索推荐 编译器
【C语言】一篇文章深入解析联合体和枚举且和结构体的区别
【C语言】一篇文章深入解析联合体和枚举且和结构体的区别
|
1月前
|
存储 编译器 C语言
C语言巧用联合体union判定数据的存储格式(大小端)
C语言巧用联合体union判定数据的存储格式(大小端)
13 1
|
1月前
|
存储 编译器 C语言
C语言从入门到实战——联合体和枚举
C语言中,联合体(union)是一种特殊的数据类型,允许存储不同类型的数据在同一块内存空间中。联合体的大小取决于其中最大的成员的大小,共享同一块内存空间的成员可以存储不同类型的数据。 联合体的定义方式与结构体类似,使用关键字union,后跟联合体的名称。联合体的成员可以是任意类型的变量,包括基本数据类型、数组、指针等。
37 0
|
1月前
|
存储 C语言
C语言枚举与联合体详解
C语言枚举与联合体详解
34 1
|
1月前
|
存储 程序员 C语言
在C语言中结构体和联合体
在C语言中结构体和联合体
|
3月前
|
存储 编译器 C语言
超全超详细的C语言结构体、位段、枚举、联合体详解
超全超详细的C语言结构体、位段、枚举、联合体详解