- 为什么要地址对齐?
- * 我们在访问内存时,如果地址是按4字节对齐,则访问效率会高很多。
- * 这个问题的原因在于访问内存的硬件电路。一般情况下,地址总线总是按照对齐后的地址来访问。
- * 例如你想得到0x00000001开始的4字节内容,系统首先需要以0x00000000读4字节,
- * 然后从中取得3字节,然后在用0x00000004作为开始地址,获得下一个四字节,
- * 在从中得到第一个字节,两次组合出你想得到的内容。但是如果地址一开始就是对齐到
- * 0x00000000,则系统只要一次读写即可。
- 所以,为了性能考虑,编译器会做地址对齐。
- 地址对齐的原则:
- 每个基本类型有自己默认的对齐值。 然后可以通过#pragma pack(2) 设置编译器的默认对齐值。取两者最小的一个作为最终对齐值。
- 若没有#pragma pack(2) 设置,那么只看基本类型自己的对齐值。
- 总之: 在允许的情况下,尽量依次填充,但是需要保证(32位系统)
- 1 char,bool只从X地址处开始存储;
- 2 short只从2X地址出开始存储;
- 3 int,float,long只从4X地址处开始存储;
- 4 double只从8X地址处开始存储;
下面是列子:
#include <iostream> using namespace std; //sizeof(union1) = 16 union union1 { long i; //4 int x[4]; //16 char ch; //1 }; //sizeof(union2) = 16 union union2{ char a[13]; int i; //由于int的存在,使得union按照四个字节来对其了 }; //sizeof(union3) = 13 union union3{ char a[13]; char i; }; /////////////// 对比node1和node2 /////////// struct node1{ //24 int j; //4 double f; //8 int i; //4 }; struct node2{ //16 int i; //4 int j; //4 double f; //8 }; /////////////// 对比node3和node4 /////////// struct node3{ //32(注意) char i; //1 int d[5]; //20 double f; //8 }; struct node4{ //40 int d[5]; //20 double f; //8 int i; //4 }; /////////////////////////////////////////// struct node5{ //32(注意) char d[10]; //10 double f; //8 int i; //4 }; struct node6{ //20 char d; //1 int f; //4 char i[10]; //10 }; //}__attribute__((aligned (1))); /////////////////////////////////////// struct node7{ //12 char x1; //1 short x2; //2 float x3; //4 char x4; //4 }; #pragma pack(1) //指定按照1字节对齐 struct node8{ //8 char x1; //1 short x2; //2 float x3; //4 char x4; //1 }; #pragma pack() //恢复缺省的字节对齐设置 //////////////////////////////////////// struct node9{ //20 char ch,*p; //1,4 union{ //4 short a,b; unsigned int c:2,d:1; }u; bool f; //1 struct node9 *next; //4 }; //测试字节对齐 void test2(){ int size; struct node1 n1; struct node2 n2; struct node3 n3; struct node4 n4; struct node5 n5; struct node6 n6; struct node7 n7; struct node8 n8; struct node9 n9; //栈生长的方向与地址增长方向相反,所以a的地址比b的地址大四字节 int a = 1,b = 2,c=3; int *p = &b; printf("%d\n",*(p+1)); //1 //测试union和struct的大小(后者会地址对齐,前者仍然输出16) printf("union1:%d\n",sizeof(union union1)); //16 printf("union2:%d\n",sizeof(union union2)); //16 printf("union3:%d\n",sizeof(union union3)); //13 //测试结构体的地址对齐 printf("************************\n"); printf("n1:%d\n",sizeof(n1)); printf("%ld\n",(unsigned long)&n1.j); printf("%ld\n",(unsigned long)&n1.f); printf("%ld\n",(unsigned long)&n1.i); printf("************************\n"); printf("n2:%d\n",sizeof(n2)); printf("%ld\n",(unsigned long)&n2.i); printf("%ld\n",(unsigned long)&n2.j); printf("%ld\n",(unsigned long)&n2.f); printf("************************\n"); printf("n3:%d\n",sizeof(n3)); printf("%ld\n",(unsigned long)&n3.i); printf("%ld\n",(unsigned long)&n3.d); printf("%ld\n",(unsigned long)&n3.f); printf("************************\n"); printf("n4:%d\n",sizeof(n4)); printf("%ld\n",(unsigned long)&n4.d); printf("%ld\n",(unsigned long)&n4.f); printf("%ld\n",(unsigned long)&n4.i); printf("************************\n"); printf("n5:%d\n",sizeof(n5)); printf("%ld\n",(unsigned long)&n5.d); printf("%ld\n",(unsigned long)&n5.f); printf("%ld\n",(unsigned long)&n5.i); printf("************************\n"); printf("n6:%d\n",sizeof(n6)); printf("%ld\n",(unsigned long)&n6.d); printf("%ld\n",(unsigned long)&n6.f); printf("%ld\n",(unsigned long)&n6.i); printf("************************\n"); printf("n7:%d\n",sizeof(n7)); printf("%ld\n",(unsigned long)&n7.x1); printf("%ld\n",(unsigned long)&n7.x2); printf("%ld\n",(unsigned long)&n7.x3); printf("%ld\n",(unsigned long)&n7.x4); printf("************************\n"); printf("n8:%d\n",sizeof(n8)); printf("%ld\n",(unsigned long)&n8.x1); printf("%ld\n",(unsigned long)&n8.x2); printf("%ld\n",(unsigned long)&n8.x3); printf("%ld\n",(unsigned long)&n8.x4); printf("************************\n"); printf("n9:%d\n",sizeof(n9)); } int main(){ int *ptr; test2(); printf("************************\n"); printf("char:%d\n",sizeof(char)); //1 printf("short:%d\n",sizeof(short)); //2 printf("int:%d\n",sizeof(int)); //4 printf("long:%d\n",sizeof(long)); //4 printf("float:%d\n",sizeof(float)); //4 printf("double:%d\n",sizeof(double)); //8 printf("pointer:%d\n",sizeof(ptr)); //4 return 0; }