`

linux 内存对齐问题分析

阅读更多
每个特定平台的编译器都有一个默认的对齐系数,gcc中是4,VC中貌似是8。也可以通过于编译命令#pragma pack(n)来指定该系数,其中n的值经测试只能是1,2和4.

对齐规则:

1、结构体的第一个数据成员放在相对位置为0的地方,以后每个数据成员按#pragma pack(n)中n指定的值和该数据成员自身长度中比较小的那个进行对齐。

2、数据成员完成对齐后,结构体本身也要对齐,按照#pragma pack(n)中n的值和结构体数据成员中最长的长度中较小的进行对齐。

验证(环境:gcc 4.4;sizeof(char)=1;sizeof(int)=4;sizeof(short)=2;sizeof(long)=4;sizeof(long long)=8):

1、默认情况(n=4)

struct st1 {

char ch;//长度1<n,按1对齐,0%1=0,起始相对位置=0;存放区间[0]

int num;//长度4=n,按4对齐, 4%4=0,起始相对位置=4;存放区间[4,7]

long lv;//长度4=n,按4对齐,8%4=0,起始相对位置=8;存放区间[8,11]

};

整个结构体成员对齐后所占的区间为[0,8],占12个字节,接着结构体本身对齐,成员中最长的是4,n也等于4,所以结构体本身按4对齐(即对齐系数)。

整个结构体的大小 = 比整个结构体数据成员所占的总空间大或相等且和对齐系数求模结果为0、与之距离最近的数。

本例中,12%4=0,所以结构体st1占12个字节的空间。

2、#pragma pack(1)(即n=1)

struct st1 {

char ch;//长度1=n,按1对齐,0%1=0,起始相对位置=0;存放区间[0]

int num;//长度4>n,按n对齐, 1%1=0,起始相对位置=0;存放区间[1,4]

long lv;//长度4>n,按n对齐,5%1=0,起始相对位置=5;存放区间[5,8]

};

整个结构体成员对齐后所占的区间为[0,8],占9个字节,接着结构体本身对齐,成员中最长的是4,n等于1,所以结构体本身按1对齐(即对齐系数)。

整个结构体的大小 = 比整个结构体数据成员所占的总空间大或相等且和对齐系数求模结果为0、与之距离最近的数。

本例中,9%1=0,所以结构体st1占9个字节的空间。

3、#pragma pack(2)(即n=2)

struct st1 {

char ch;//长度1<n,按1对齐,0%1=0,起始相对位置=0;存放区间[0]

int num;//长度4>n,按n对齐, 2%2=0,起始相对位置=2;存放区间[2,5]

long lv;//长度4>n,按n对齐,6%2=0,起始相对位置=6;存放区间[5,8]

};

整个结构体成员对齐后所占的区间为[0,8],占9个字节,接着结构体本身对齐,成员中最长的是4,n等于2,所以结构体本身按2对齐(即对齐系数)。

整个结构体的大小 = 比整个结构体数据成员所占的总空间大或相等且和对齐系数求模结果为0、与之距离最近的数。

本例中,10%2=0,所以结构体st1占10个字节的空间。

为什么说#pragma pack(n)中n只能是1,2,4呢?

比如3,如果n=3,在编译的时候会警告“对齐边界必须是 2 的较小次方,而不是 3”,也就是说是不起作用的,按默认对齐系数对齐。

再如8,会有什么结果?看下一例:

4、#pragma pack(8)(即n=8)

struct siz {

char v1;

long long v2;

short v3;

int v4;

};

如果8起作用,分析一下:

struct siz {

char v1;//长度1<n,按1对齐,0%1=0,起始相对位置=0;存放区间[0]

long long v2;//长度8=n,按8对齐,8%8=0,起始相对位置=8;存放区间[8,15]

short v3;//长度2<n,按2对齐,16%2=0,起始相对位置=16;存放区间[16,17]

int v4;//长度4<n,按4对齐,20%4=0,起始相对位置=20;存放区间[20,23]

};

整个结构体成员对齐后所占的区间为[0,23],占24个字节,接着结构体本身对齐,成员中最长的是8,n等于8,所以结构体本身按8对齐(即对齐系数)。24%8=0,所以占24个字节。

然而,很不幸,运行的结果是20.

接下来,用默认的对齐系数4来分析一下:

struct siz {

char v1;//长度1<4,按1对齐,0%1=0,起始相对位置=0;存放区间[0]

long long v2;//长度8>4,按4对齐,4%4=0,起始相对位置=4;存放区间[4,11]

short v3;//长度2<4,按2对齐,12%2=0,起始相对位置=12;存放区间[12,13]

int v4;//长度4=4,按4对齐,16%4=0,起始相对位置=16;存放区间[16,19]

};

整个结构体成员对齐后所占的区间为[0,19],占20个字节,接着结构体本身对齐,成员中最长的是8,n等于4,所以结构体本身按4对齐(即对齐系数)。20%4=0,所以占20个字节。与运行结果一致。

综上分析,当n=8的时候gcc仍然使用的是默认的对齐系数4.
分享到:
评论

相关推荐

    嵌入式Linux C编程入门(第2版) PPT

    7.3.2 数据对齐 218 7.3.3 字节顺序 218 7.4 c和汇编的接口 219 7.4.1 内嵌汇编的语法 219 7.4.2 编译器优化介绍 221 7.4.3 c语言关键字volatile 222 7.4.4 memory描述符 222 7.4.5 gcc对内嵌...

    C++中类的内存空间大小(sizeof)分析

    我认为对齐是C语言中让很多初学者都拿不准摸不透的问题,特别是在跨平台的情况下,对齐这种问题更加的复杂多变,每一种系统都有自己独特的对齐方式,在Windows中经常是以结构体重最大内置类型的存储单元的字节数作为...

    Linux应用程序开发指南

    第一部分介绍Linux GUI编程架构以及编程基础知识,第二部分介绍Linux 编程常用C语言函数库glibc、构件库Gtk+、Gnome,第三部分介绍Linux下的GUI生成器Glade,第四部分介绍Linux编程调试工具gdb及xxgdb。第五部分包括...

    Linux程序开发Gtk+ Gnome库

    10.2 对齐构件GtkAlignment 166 10.3 框架构件GtkFrame 167 10.4 比例框架构件GtkAspectFrame 169 10.5 分栏窗口构件GtkPanedWindow 170 10.6 视角构件GtkViewport 174 10.7 滚动窗口构件GtkScrolled Window 175 ...

    蓝梦软件BestRecoveryForLinux数据恢复软件

    本软件采用高效的数据结构以及分析算法,从磁盘底层读出原始的扇区数据,将丢失或损坏的目录和文件在内存中进行快速精准重建。支持IDE/SCSI/SATA/SAS/USB等接口硬盘,RAID磁盘等存储介质,支持Ext2/Ext3/Ext4/...

    Reversing:逆向工程揭密

    3.6.3 区段对齐(Section Alignment) 95 3.6.4 动态链接库 96 3.6.5 头部 97 3.6.6 导入与导出 99 3.6.7 目录 99 3.7 输入与输出 103 3.7.1 I/O系统 103 3.7.2 Win32子系统 104 3.8 结构化异常处理 105 3.9 结论 ...

    uboott移植实验手册及技术文档

    4、交叉编译器 arm-softfloat-linux-gnu-gcc-3.4.5 【实验步骤】 一、建立自己的平台类型 (1)解压文件 #tar jxvf u-boot-1.3.1.tar.bz2 (2)进入 U-Boot源码目录 #cd u-boot-1.3.1 (3)创建自己的开发板...

Global site tag (gtag.js) - Google Analytics