Linux下字节对齐准则
一、对齐模数许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数。对于基本数据类型(int char),他们占用的内存空间在一个确定硬件系统下有个确定的值。而结构体成员内存分配情况却有所不同。就GUNGCC编译器而言,结构体的成员其对齐模
一、对齐模数
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数。
对于基本数据类型(int char),他们占用的内存空间在一个确定硬件系统下有个确定的值。而结构体成员内存分配情况却有所不同。
就GUN GCC编译器而言,结构体的成员其对齐模数只能为1,2和4,或其整数倍,这一点和VS等编译器不太相同。
二、结构体字节对齐准则
结构体字节对齐的细节和具体编译器实现相关,但一般而言,满足三个准则:
1. 结构体变量的首地址能够被其最宽基本数据类型成员的大小所整除;
2. 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;
3. 结构体的总大小为结构体最宽基本数据类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。
4.对于结构体嵌套结构体,其对齐扔按照基本数据类型拆分来分析。
示例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct sub_struct {
char name[10];//数组也算简单的复合类型,其存储还是以基本类型来存储
};
struct stu {
char sex;
int length;
char index;
struct sub_struct sub;//结构体只是一个复合类型,内存的存储实际上是对基本类型的存储
};
/*从低位到高位显示打印内存所存的内容*/
void display_mem(char *start, int size)
{
int i;
for(i = 0; i < size; i++)
printf("0x%02x ", start[i]);
printf("\n");
}
int main(void)
{
int size;
struct stu std = {
.sex = 1,
.length = 1,
.index = 1,
.sub = 1,
};
size = sizeof(struct stu);
printf("size is %d\n", size);
display_mem((char *)&std, size);
return 0;
}
因为上述结构体对齐的原因,将结构体成员按照大小递增/递减方式排序,可以减少结构体占用的空间大小。而这样同时使得对整个结构体的存取的效率变高了(占用小,整个的访问次数可以降低)。
对于空结构体,有的文章说sizeof也会占1个字节,但我试验中,sizeof 空结构体 的结构是0,我的环境为Linux 64位。
三、联合体
union(共用体)的各个成员是以同一个地址开始存放的,每一个时刻只可以存储一个成员,这样就要求它在分配内存单元时候要满足两点:
1.一般而言,共用体类型实际占用存储空间为其最长的成员所占的存储空间;
2.若是该最长的存储空间对其他成员的元类型,(如果是复合数据类型,取其最宽基本数据类型的数据长度为witch,例int a[5]为4;struct str{char a; int b}为4.)不满足整除关系,该最大空间自动延伸到witch的整倍数;
代码示例:
//
示例1:#include<stdio.h>
#include<stdlib.h>
#include<string.h>
union mm {
char a[5];
int i;
};
int main(void)
{
printf("mm size is %ld\n", sizeof(union mm));
return 0;
}
//
示例2:#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct str {
char name;
int n;
};
union mm {
char a[9];
struct str st;
};
int main(void)
{
printf("mm size is %ld\n", sizeof(union mm));
return 0;
}
更多推荐
所有评论(0)