C语言之内存对齐小析

    技术2022-05-20  53

    内存对齐小例: #include <stdio.h> struct Test_one { char c1; short s; char c2; int i; }; struct Test_two { char c1; char c2; short s; int i; }; int main( ) { struct Test_one one; struct Test_two two; printf( "sizeof(one)=%d;sizeof(two)=%d/n",sizeof( one ),sizeof( two )); printf( "this is the Test_one's address detial/n c1 %p,s %p,c2 %p,i %p/n", (unsigned int )( void * )&one.c1-( unsigned int )( void* )&one, (unsigned int)( void * )&one.s-( unsigned int )( void*) &one, ( unsigned int)( void * )&one.c2-( unsigned int )( void*) &one, ( unsigned int)( void * )&one.i-( unsigned int )( void*) &one); printf( "this is the Test_two's address detial/n c1 %p,c2 %p,s %p,i %p/n", (unsigned int )( void * )&two.c1-( unsigned int )( void* )&two, (unsigned int)( void * )&two.c2-( unsigned int )( void*) &two, ( unsigned int)( void * )&two.s-( unsigned int )( void*) &two, ( unsigned int)( void * )&two.i-( unsigned int )( void*) &two); return 0; } 下面是结果:(注“nil”表示0x00) sizeof(one)=12;sizeof(two)=8 this is the Test_one's address detial c1 (nil),s 0x2,c2 0x4,i 0x8 this is the Test_two's address detial c1 (nil),c2 0x1,s 0x2,i 0x4

    字、双字、四字在自然边界上不许要内存对齐,所谓的自然边界分别为偶地址、被4整除的地址、被8整除的地址; 呵呵,你要问一字节的自然边界那?想想吧~_~ 之所以要进行内存对齐是为了内够减少从内存中取数据的次数,位于自然边界上的数据在一个总线周期就可溢取得,否则就需要2个或多个。 另外,我们也可以设置是否允许编译器进行内存对齐: #pragma pack()可以改变编译器的默认对齐方式, ex: #pragma pack(n) code... //这两句之间的代码将按招n字节对齐 #pragma pack() 注意:《C语言深度解剖》里面还提到“如果#pragma pack(n)中的n比每个数据的对齐地址大的话,就采用数据本身的对齐地址”;总起来说就是取二者中的最小的来进行对齐,如果不够的话就填充空字节。 比如: #pragma pack(4) char c1="a"; int mm=34; #pragma pack() 由于char/int的对齐地址都要比4小,所以就采用变量本身的对齐方式。 复杂类型(如struct)的默认对齐方式是它最长的成员对齐方式,这样在成员是复杂类型的时候,可以最小化长度。 如: #pragma pack(8) struct Test_one { char a; long b; //为了方便说明long按照4字节! }; struct Test_two { char c; Test_one d; long long e;//long long =8B }; sizeof(Test_one)=8; //a 0x00 ; b 0x04 sizeof(Test_two)=24; //因为Test_one最大的对齐地址为long的4,所以在Test_two中进行对齐的时候采用4 //c 0x00 ; d 0x04~0x0c ; e 0x10~0x18 是舍弃内存空间,还是运行效率,这是一个折中的问题。


    最新回复(0)