#pragma pack記憶體對齊的實現以及相關微軟面試題

念你瑤瑤無期發表於2020-11-13

什麼是記憶體對齊?
-不同型別的資料在記憶體中按照一定的規則排布
-而不一定是順序的一個接一個的排序

struct Test1
{
	char c1;
	short s;
	char c2;
	int i;
};

struct Test2
{
	char c1;
	char c2;
	short s;
	int i;
};
sizeof(struct Test1)=?
sizeof(struct Test2)=?

答案是12和8

分析:

在這裡插入圖片描述

為什麼需要記憶體對齊?
	-CPU對記憶體的讀取不是連續的,二是分塊讀取的,塊的大小隻能是1、2、4、8、16...位元組
	-當讀取操作的資料未對齊,則需要兩次匯流排週期來訪問記憶體,因此效能會大打折扣
	-某些硬體平臺只能從規定的相對地址處讀取特定型別的資料,否則產生硬體異常
#pragma pack 用於指定記憶體對齊方式,能夠改變編譯器預設對齊方式
#include<stdio.h>

#pragma pack(4)
struct Test1		//對齊引數  偏移地址  大小
{			//1	   0         1
	char c1;	//2        2         2
	short s;	//1	   4         1
	char c2;	//4        8         4
	int i;
};			//大小為8+4=12
#pragma pack()

#pragma pack(4)
 struct Test1		//對齊引數  偏移地址  大小
{			//1	    0        1
 char c1;		//1         1        1
 char c2;		//2         2        2
 short s;      		//4         4        4
 int i;
};			//大小為4+4=8
#pragma pack()
編譯器預設為pack(4)
struct 佔用記憶體大小
-第一個成員起始於0偏移處
-每個成員按其型別大小和pack引數中較小的一個進行對齊
	·偏移地址必須能被你對齊引數整除
	·結構體成員的大小取其內部長度最大的資料成員作為其大小
-結構體總長度必須為所有對齊引數的整數倍

微軟面試題:

#include<stdio.h>
#pragma pack(8)
struct S1  	
{   		//對齊引數      偏移地址  大小
 short a;	//2        	0         2
 long b; 	//4             4         4
}; 		//大小4+4=8
struct S2  	
{  		//對齊引數      偏移地址  大小
 char c1;	//1        	0         1
 struct S1 d;   //4       	4         8 //對齊引數為結構體成員長度最大的成員
 double e;  	//8          	16        8
};   		//大小為16+8=24
 
 #pragma pack()
int main()
{
	printf("%d\n",sizeof(struct S1));
	printf("%d\n",sizeof(struct S2));
	return 0;
}   

不同編譯器輸出結果不一樣
gcc編譯器暫時不支援8位元組對齊,輸出結果為20(pack(4))
vs編譯器支援8位元組對齊,輸出結果為8和24
在這裡插入圖片描述

相關文章