Linux C語言: 結構體內存對齊和補齊原理



結構體內存對齊

系統:Linux 64位CenOS 7 GCC編譯器

內存對齊的表現

typedef struct {

int a; // 4 bytes

char b[5]; // 5 bytes

double c; // 8 bytes

int d; // 4 bytes

short e; // 2 bytes

}MemAlign;

Sizeof(MemAlign) = 32

單個參數計算總和為23個字節,而整個結構體卻是32個字節,這是為什麼呢?


為什麼要進行內存對齊?

我們大多數人在沒有搞清楚CPU是如何讀取數據的時候,基本都會認為CPU是一字節一字節讀取的,但實際上它是按照塊來讀取的,塊的大小可以為2字節,4字節,8字節,16字節。Linux 64位下默認為8字節。

1、平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定類型的數據,否則拋出硬件異常,特別是嵌入式設備。

2、性能原因:數據結構(尤其是棧)應該儘可能地在自然邊界上對齊。原因在於,為了訪問未對齊的內存,處理器需要作兩次內存訪問;而對齊的內存訪問僅需要一次訪問。


Linux C語言: 結構體內存對齊和補齊原理

對齊補齊原則

有點文章給出了很複雜的解釋,我總結就這兩個

(1)第一個成員首地址從0開始。

(2)第一個成員內存大小必須是對齊字節數的整數倍或被整除。從第二個成員開始累加前面所有成員內存大小必須是對齊字節數的整數倍。

<code>#include <stdio.h>
#include <memory.h>


#pragma pack(8)
typedef struct {
int a; // 4 bytes
char b[5]; // 5 bytes
double c; // 8 bytes
int d; // 4 bytes
short e; // 2 bytes
}MemAlign;


typedef struct {
int a;
MemAlign ma;
char c;

} NewAlg;

#pragma pack(8)

int main(int argc, char argv[])

{

MemAlign mA;
int mlen = sizeof(MemAlign);
int al = sizeof(mA.a);
int bl = sizeof(mA.b);
int cl = sizeof(mA.c);
int dl = sizeof(mA.d);
int el = sizeof(mA.e);

printf("al = %d, bl = %d, cl = %d, dl = %d, el = %d, sum(%d), sizeof = %d \\n",
al, bl, cl, dl, el,(al+bl+cl+dl+el), mlen);

printf("a=%x, b=%x,c=%x,d=%x,e=%x\\n",&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;
int i;
for(i = 0; i < mlen; i++)
{
printf("%x ", *(p+i));
}


printf(" \\n");

int nlen = sizeof(NewAlg);
printf("nlen = %d \\n", nlen);


return 0;
}
/<memory.h>/<stdio.h>/<code>



分享到:


相關文章: