关于结构体的内存对齐

本文以gcc version 4.4.3 64x86环境为例,来分析结构体中各成员如何进行对齐。

我们要注意两个方面:

1)结构体成员变量对存放的起始地址有要求

2)结构体变量占用的总长度也有要求

结构体对齐规则如下:

1、数据成员最终的存放地址:对齐在自身类型长度和#pragma pack(value)指定值中较小的值上。

例如char型, 其占用1个字节, #pragma pack(4)指定值是4, 那么char类型本身存放的起始地址是1个字节对齐,也就是其所存放的

起始地址要求被1除尽. 64位系统long 类型占用8个字节,如果#pragma pack(4),那么两者取小值,即4,那么long起始地址是4字节对齐。

2、结构体的总长度:对齐在成员类型长度最大的值和pragma pack(value)指定值中较小的值上。

结构体最终的总长度,应取成员类型长度最大值与#pragma pack(value)指定值中较小的值的整数倍。

看下面几个例子:(当前gcc version 4.4.3,64位x86环境下,8位对齐,可使用#pragma pack(value)修改)

例1: 


#include <stdio.h>
#pragma pack(push)
typedef struct CHIP
{
char a;
int b;
char c;
long d;
}test;
void main()
{
test h;
printf("size of struct = %d\n",sizeof(h));
}



分析: pragma pack(push),系统default对齐为8位

char a成员,char类型长度1,pragma pack(push) (default为8),取小的1,其存储位置0x00000000

int b成员,int类型长度为4,pragma pack(8),两者取相对较小值为4,因此int的存储地址需要4字节对齐,在0x00000004~0x00000007

char c成员,char 类型长度为1, 即存储位置为0x00000008 ~ 0x00000009

long c成员,long类型长度为8, pragma pack(8), 需要8位对齐,因此c的存储位置为0x00000010 ~ 0x00000017

最终结构体的size需要在类型长度最大的值即long (长度为8) 和#pragma pack(push) (当前环境default为8)指定值中较小的对齐,

即8位对齐,因此最终长度还是24.



例2, 修改code如下


#include <stdio.h>
#pragma pack(4)
typedef struct CHIP
{
char a;
int b;
char c;
long d;
}test;
void main()
{
test h;
printf("size of struct = %d\n",sizeof(h));
}



说明: #pragma pack(4)指定4位对齐

char a    0x00000000 ~ 0x00000000

int b     0x00000004 ~ 0x00000007

char c    0x00000008 ~ 0x00000008

long d    0x0000000C ~ 0x00000013

结构体总长度为20,4位对齐最终的结构体size为20


例3, 修改code如下

#include <stdio.h>

typedef struct CHIP
{
long b;
char c;
char d;
}test;
void main()
{
test h;
printf("size of struct = %d\n",sizeof(h));
}

说明: 未指明 #pragma pack() default 为8 byte对齐

long b    0x00000000 ~ 0x00000007

char c     0x00000008 ~ 0x00000008

char d    0x00000009 ~ 0x00000009

补齐    0x0000000A ~ 0x000000F

结构体总长度为16,8位对齐最终的结构体size为16



可参考另一篇转载博文  《失落的C语言结构体封装艺术》  http://blog.csdn.net/chrovery/article/details/18989779

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值