【转】C语言中数据类型和结构体大小问题

在c语言中,如果运行平台是32位的,则int所占字节数为4字节,而short为两个字节,无符号数值类型和对应数值类型大小一致.

 
  
struct s1{
char * ptr,ch;
union A{
short a,b;
unsigned
int c: 2 ,d: 1 ;
};
struct s1 * next;
};
// 这样是12个字节

 
  
1 struct s1{
2 char * ptr,ch;
3 union {
4 short a,b;
5 unsigned int c: 2 ,d: 1 ;
6 };
7 struct s1 * next;
8 };
9
10 // 这样是16个字节

上述两个的主要区别在联合的处理上,联合如果不声明A,表示声明了结构体的一个成员,是需要占内存的,而如果声明A,表示定义的是一个类型,不用占用内存。联合的大小取决于其中最大的数据类型的内存分配大小,联合在内存中是叠加存放的。指针相当于无符号的整形,32位系统中是32位4个字节,涉及到取大小的时候要考虑内存对齐的影响,因此字面所占字节和实际运行中的不一致,一般求内存大小指的是实际运行大小.

因此第一组的内存大小即为:一个char类型的指针,一个char类型的变量和一个结构体类型指针的大小,考虑内存对齐,分别为4字节,4字节(实际占1字节),4字节,因此结果是12字节

而第二组的内存大小,因为union作为结构体成员出现,因此考虑其内存,同时内存叠加,short占2个字节,unsigned int占4个字节,因此union的总体大小是4个字节.结果为16字节

为了使CPU对变量进行快速高效的访问,变量的起始地址应该满足某些特性,即所谓的对齐。关于字节对齐有两个重要的宏,#pragma pack (n)和#pragma pack 第一个宏是强制编译器一般以n的倍数进行地址对齐(还有特殊情况以小于n的字节数进行对齐),第二个宏结束前面设置的对齐方式,恢复到编译器默认的对齐方 式。在Visual C++下默认的字节对齐数为8字节。

    结构体中的变量item在结构体中相对于首地址的偏移量应该是 X 的倍数,X 由如下式子确定:X=min(n,sizeof(item)),(注意:这时的内存计算方式和前面两个结构体的内存计算方式存在一些微小的区别)举个例子(设n为8):struct Test { char c1; char c2; int i}; 如果定义了变量Test t ,那么在存储 t 的 i 时 X 就应该是min(8,sizeof(int))即为4的倍数,即 i 相对于结构体首地址的偏移量必须是4的倍数,所以 t 的大小就应该为8字节(在c1和c2后填充了两个字节以满足前述条件)。对于struct { char c1; char c2}不会出现填充的的情况,每个成员相对首地址的偏移量也满足是X的倍数(此时X为1),其大小为2字节。      

    而对于结构struct {char c1; double d;},默认情况下这种结构体变量占用16字节(在c1后填充了7个字节以满足字节对齐)。如果强制编译器以4字节对齐,即在声明这种结构的变量前面 有#pragma pack (4),此时X为4,则此种类型结构体变量占用的内存为12字节。

    再看 struct {char c1; double d; char c2;}; 在默认字节对齐的方式下,输出其大小为24,呵呵,这是因为编译器还有一条规定:结构体变量的大小必须要为X(同上定义)的倍数,如果不满足,就会在最后一个成员后填充最少字节数以满足此条件。 如果定义此结构体前有#pragma pack(4),则输出大小为16。

    还有一种特殊情况,就是空结构体。在Visual C++下其大小为1,即struct{}类型的变量在VC下输出其大小是1,解释就是VC为每个结构体变量分配一个字节的内存,以使该变量有个地址;而在 gcc下输出其大小为0,我的理解是既然此结构体一个成员都没有,程序中就不会访问它,因此也不必分配内存,如果编译器碰到有访问此结构体成员的情况就会 报错。

    最后一种情况,结构体成员中有结构体成员的情况,如 struct test1 { char c1; int i ; char c2 ;};        struct test2 { int i; struct test1 t1; char c2; };此时考虑在确定上述的X时会把t1拆散成基本数据类型来处理,而考虑test2结构大小时又会把t1作为一个整体来对待,但此时所谓的整体是把test1中确定的那个最大的X拿出来来确定test2的X。 故默认情况下,结构test2类型变量的大小为:20(test1中最大的X被确定为4,test2中也为4,t1占12个字节,在c2后又填充了3字节,总共20字节)。举个例子:

    struct test1 {char c1;        double d;           char c2;};

    struct test2 { int i;      struct test1 t1;         char c2;};

    默认情况下,结构体test2的大小为40(最大的X被确定为8),强制4字节对齐时大小为24。其实这可以理解为编译器的另一条规则:结构体的首地址必须为其最大的那个X的整数倍。

转载于:https://www.cnblogs.com/cylee025/archive/2011/05/27/2059468.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值