又是菜雞的記錄日誌,局部變量大小,坑人的編譯器

其實主要是想說明編譯器太坑了(以下都是在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.根據小值對齊
附:結構體裏結構體就要看內部結構體的數據寬度而形成的類數組,
個人總結:不確定對錯,目前沒出問題

完事,因爲編譯器選擇,基礎規則也有所變化,留意這個坑點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章