本文为摘抄并修改,原文:http://www.cnblogs.com/dolphin0520/archive/2011/10/03/2198493.html
联合体例子:
union U
{
char s[9];
int n;
double d;
};
s占9字节,n占4字节,d占8字节,因此sizeof(U)至少9字节。然而用运算符sizeof测试其大小为16。这是因为字节对齐,9既不能被4整除,也不能被8整除。因此补充字节到16,这样就符合所有成员的自身对齐了。
从这里可以看出联合体所占的空间不仅取决于最宽成员,还跟所有成员有关系。即其大小必须满足两个条件:
- 1)大小足够容纳最宽的成员;
- 2)大小能被其包含的所有基本数据类型的大小所整除。
#include <stdlib.h>
#include <stdio.h>
union U1
{
char s[9];
int n;
double d;
};
union U2
{
char s[5];
int n;
double d;
};
int main(int argc, char *argv[])
{
union U1 u1;
union U2 u2;
printf("%ld\n",sizeof(u1));
printf("%ld\n",sizeof(u2));
printf("0x%p\n",&u1);
printf("0x%p\n",&u1.s);
printf("0x%p\n",&u1.n);
printf("0x%p\n",&u1.d);
u1.n=1;
printf("%d\n",u1.s[0]);
printf("%lf\n",u1.d);
u1.n=97;
printf("%c\n",u1.s[0]);
return 0;
}
cloud@cloud:/web/code/c$ ./union
16
8
0x0x7ffffdc698a0
0x0x7ffffdc698a0
0x0x7ffffdc698a0
0x0x7ffffdc698a0
1
0.000000
a
对于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。
至于
u1.n=97;
printf("%c\n",u1.s[0]);
return 0;
我这里写入的是4字节的int型数据97;
却以字符串格式来打印,打印出ascii对应97的字母a。
为什么要内存对齐?
http://www.jianshu.com/p/0355f83ff557