Linux C语言: 结构体内存对齐和补齐原理

结构体内存对齐
系统:Linux64位CenOS7GCC编译器
内存对齐的表现
typedefstruct{
inta;//4bytes
charb[5];//5bytes
doublec;//8bytes
intd;//4bytes
shorte;//2bytes
}MemAlign;
Sizeof(MemAlign)=32
单个参数计算总和为23个字节 , 而整个结构体却是32个字节 , 这是为什么呢?
为什么要进行内存对齐?
我们大多数人在没有搞清楚CPU是如何读取数据的时候 , 基本都会认为CPU是一字节一字节读取的 , 但实际上它是按照块来读取的 , 块的大小可以为2字节 , 4字节 , 8字节 , 16字节 。 Linux64位下默认为8字节 。
1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据 , 否则抛出硬件异常 , 特别是嵌入式设备 。
2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐 。 原因在于 , 为了访问未对齐的内存 , 处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问 。
Linux C语言: 结构体内存对齐和补齐原理
文章图片
对齐补齐原则
有点文章给出了很复杂的解释 , 我总结就这两个
(1)第一个成员首地址从0开始 。
【Linux C语言: 结构体内存对齐和补齐原理】(2)第一个成员内存大小必须是对齐字节数的整数倍或被整除 。 从第二个成员开始累加前面所有成员内存大小必须是对齐字节数的整数倍 。
#include
#include
#pragmapack(8)typedefstruct{inta;//4bytescharb[5];//5bytesdoublec;//8bytesintd;//4bytesshorte;//2bytes}MemAlign;typedefstruct{inta;MemAlignma;charc;}NewAlg;#pragmapack(8)intmain(intargc,charargv[]){MemAlignmA;intmlen=sizeof(MemAlign);intal=sizeof(mA.a);intbl=sizeof(mA.b);intcl=sizeof(mA.c);intdl=sizeof(mA.d);intel=sizeof(mA.e);printf("al=%d,bl=%d,cl=%d,dl=%d,el=%d,sum(%d),sizeof=%dn",al,bl,cl,dl,el,(al+bl+cl+dl+el),mlen);printf("a=%x,b=%x,c=%x,d=%x,e=%xn",&mA.a,&mA.b,&mA.c,&mA.d,&mA.e);memset(&mA,0x0,mlen);memset(&mA.a,0x1,al);memset(&mA.b,0x2,bl);memset(&mA.c,0x3,cl);memset(&mA.d,0x4,dl);memset(&mA.e,0x5,el);char*p=(char*)&mA;inti;for(i=0;i<mlen;i++){printf("%x",*(p+i));}printf("n");intnlen=sizeof(NewAlg);printf("nlen=%dn",nlen);return0;}


    推荐阅读