其實主要是想說明編譯器太坑了(以下都是在32位環境下)
剛開始使用的是vs2010,一個int a ,緩衝區都要增大0xC
我人都傻了,兩個int 增大0x18, char c[12] 增大0x20
一個double 直接佔用0x10 ,值放在0x4-0xC 形成 4 8 4
瘋狂的浪費空間,我也不曉得原因,先做個記錄帖,以後再翻案吧
然後再裝一個vc6,就完全符合我的預期
局部變量(定義局部變量在緩衝區中)
char a; 四個字節
short a;四個字節
int a; 四個字節
double a;八個字節
char a[3];char a[4] ;四個字節
總結1:局部變量會根據CPU寬度進行對齊
注意 連續兩個char 也分別佔四字節,總共佔8字節,原因,局部變量使用頻率較高,一般數量不多,使用空間換時間,CPU執行取存四個字節最快
例如:char還要有無符號擴展才能傳,就麻煩,四字節就直接傳,將局部變量設置爲0x00 00 00 char 這樣只要mov al,XXX或者mov byte ptr [],xxx 減少了一條命令
但是如果在結構體或者字符串中時,就會進行合併
#pragma pack(n) vc6默認pragma pack(8) (這裏沒看官方文檔,聽海哥講的,不確定)
規則是 min(n,類型),並且最後長度爲n的整數倍,n只能取2,4,8,16(不確定)寫6警告但是對齊不以6
寫的過大,編譯器會將其變小到最大基礎變量長度,(自己遍歷一遍找個最大基礎定義數據類型)
#pragma pack(8)
struct {
int a; //min(4,8) 4 4???
char b: //min(1,8) 1 4 1 ???
short c; //min(2,8) 2 4 1 ?2 ??? 注意short要以2對齊,前面就5個所以補一個
double d: //min(8,8) 8 4 1 ? 2 8 結束
};
#pragma pack()
4 1 1 2 int char NULL short
8 double
共計16字節
#pragma pack(1)
struct { min(類型,n) 小的數 實際佔的空間
int a; //min(4,1) 1 4
char b: //min(1,1) 1 4 1
short c; //min(2,1) 1 4 1 2
double d: //min(8,1) 1 4 1 2 8 結束
};
#pragma pack()
4 1 2 8
共計15字節
waring :expected pragma parameter to be '1', '2', '4', '8', or '16' 編譯器警告
繼續提升難度
struct test
{
char a[6];
};
struct test2
{
char a;
int b;
};
struct ttest
{
char a;
struct test tt;
char b;
int c;
};
struct ttest2
{
char a;
struct test2 tt;
char b;
int c;
};
根據內存 ttest
a tt.a[0] tt.a[1] tt.a[2]
tt.a[3] tt.a[4] tt.a[5] b
c c c c
12個字節
根據內存 ttest2
a ? ? ?
tt.a ? ? ?
tt.b tt.b tt.b tt.b
b ? ? ?
c c c c
20字節,好難啊
爲啥ttest 合併了數組 ttest2沒有合併呢
猜測 test 和 test2的字符寬度不一樣
test的字符寬度爲1
即 ttest
char a
char tt[6]
char b
int c
test2的字符寬度爲4
即ttest2
char a
int tt[2]
char b
int c
解決,感覺沒毛病
總結2:
結構體,如果不加#pragma pack() 根據最長數據類型對齊(數組算單個元素長度,結構體裏結構體也是這樣計算)
如果加了就會根據兩者小的那個進行數據類型對齊。
1.即遍歷結構體 get 最長數據類型長度
2.最長數據類型長度和 #pragma pack(n) 取小值
3.根據小值對齊
附:結構體裏結構體就要看內部結構體的數據寬度而形成的類數組,
個人總結:不確定對錯,目前沒出問題
完事,因爲編譯器選擇,基礎規則也有所變化,留意這個坑點。