windows和Linux内存的对齐方式
2020-12-13 14:17
标签:编译器 操作系统 数据 内存 合并 windows和Linux内存的对齐方式 标签:编译器 操作系统 数据 内存 合并 原文地址:http://blog.csdn.net/hustyangju/article/details/40591559
struct xx{
char b;
int a;
int c;
char d;
};
{
struct xx bb;
printf("&a = %p\n", &bb.a);
printf("&b = %p\n", &bb.b);
printf("&c = %p\n", &bb.c);
printf("&d = %p\n", &bb.d);
printf("sizeof(xx) = %d\n", sizeof(struct xx));
}
&b = ffbff5e8
&c = ffbff5f0
&d = ffbff5f4
sizeof(xx) = 16
struct xx{
char b;
char d;
int a;
int c;
};
#pragma pack(4)
struct xx{
char b;
long long a;
int c;
char d;
};
#pragma pack()
{
struct xx bb;
printf("&a = %p\n", &bb.a);
printf("&b = %p\n", &bb.b);
printf("&c = %p\n", &bb.c);
printf("&d = %p\n", &bb.d);
printf("sizeof(xx) = %d\n", sizeof(struct xx));
}
打印结果为:
&b = ffbff5e0
&c = ffbff5ec
&d = ffbff5f0
sizeof(xx) = 20
内存对齐是操作系统为了快速访问内存而采取的一种策略,简单来说,就是为了放置变量的二次访问。操作系统在访问内存 时,每次读取一定的长度(这个长度就是操作系统的默认对齐系数,或者是默认对齐系数的整数倍)。如果没有内存对齐时,为了读取一个变量是,会产生总线的二 次访问。
char b; //0xffbff5e8
int a; //0xffbff5e9
int c; //0xffbff5ed
char d; //0xffbff5f1
};
内存对齐的问题主要存在于理解struct等复合结构在内存中的分布。
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐。
1、对于microsoft的编译器,每种基本类型的大小即为这个k。大体上char类型为8,int为32,long为32,double为64。
2、对于linux下的gcc编译器,规定大小小于等于2的,k值为其大小,大于等于4的为4。
struct test1
{
char a;
short b;
int c;
long d;
double e;
};
2 0 4 0 8 0 0 0 10 0 0 0 0 0 0 0 0 0 0 0 0 0 40 40
显然推断是正确的。
假设从0地址开始,首先a的k值为1,它的首地址可以使任意位置,所以a占用第一个字节,即地址0;然后b的k值为2,他的首地址必须是2的倍数,不能是1,所以地址1那个字节被填充,b首地址为地址2,占用地址2,3;然后到c,c的k值为4,他的首地址为4的倍数,所以首地址为4,占用地址4,5,6,7;再然后到d,d的k值也为4,所以他的首地址为8,占用地址8,9,10,11。最后到e,从这里开始与microsoft的编译器开始有所差异,他的k值为不是8,仍然是4,所以其首地址是12,占用地址12-19。显然其大小为20。
我们建立一个test1类型的变量,a、b、c、d、e分别赋值2、4、8、16、32。然后从低地址依次打印出内存中每个字节对应的16进制数为:
2 0 4 0 8 0 0 0 10 0 0 0 0 0 0 0 0 0 40 40
struct test2
{
char f;
struct test1 g;
};
{
unsigned int a:4;
unsigned int b:4;
char c;
};
或者
struct test3
{
unsigned int a:4;
int b:4;
char c;
};
如:test3中,a、b可作为一个整体,他们作为一个int型数据来看待,所以test3的大小为8字节。并且a与b的值在内存中从低位开始依次排列,位于4字节区域中的前0-3位和4-7位
struct test4
{
unsigned int a:30;
unsigned int b:4;
char c;
};
那么test4的大小就为12个字节,并且a与b的值分别分布在第一个4字节的前30位,和第二个4字节的前4位。
struct test5
{
unsigned int a:4;
unsigned char b:4;
char c;
};
{
unsigned int a:4;
unsigned int b:4;
char c;
};
gcc下,相邻各成员,不管类型是否相同,占的位数之和超过这些成员中第一个的大小的时候,在结构中以k值为1对齐,在结构外k值为其基本类型的值。不超过的情况下在内存中依次排列。
如test3,其大小为4。a,b的值在内存中依次排列分别为第一个四字节中的0-3和4-7位。
struct test4
{
unsigned int a:20;
unsigned char b:4;
char c;
};
test4的大小为4个字节,并且a与b的值分别分布在第一个4字节的0-19位,和20-23位,c存放在第4个字节中。
如过test5是以下形式
struct test5
{
unsigned int a:10;
unsigned char b:4;
short c;
};
那么test5的大小应为8字节。即
{
unsigned int a:20;
unsigned char b:4;
short c;
};
上一篇:截取铃声python代码