一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

【程序員一枚】C++基礎(chǔ)之內(nèi)存對(duì)齊

 pgj555 2014-04-29

今天又遇到一個(gè)惡搞問(wèn)題,內(nèi)存對(duì)齊

為什么會(huì)出現(xiàn)內(nèi)存對(duì)齊?

效率問(wèn)題,對(duì)于結(jié)構(gòu)體,訪問(wèn)未對(duì)齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問(wèn);而對(duì)齊的內(nèi)存訪問(wèn)僅需要一次訪問(wèn)。

為什么要考慮內(nèi)存對(duì)齊?

跨平臺(tái),跨語(yǔ)言,跨編譯器的時(shí)候因?yàn)閮?nèi)存對(duì)齊的原因可能造成設(shè)置的數(shù)據(jù)和獲取的數(shù)據(jù)不同。

舉幾個(gè)簡(jiǎn)單的例子,假如您在32位操作系統(tǒng)下將上面的結(jié)構(gòu)體直接以取地址的方式把該結(jié)構(gòu)體寫(xiě)入到一個(gè)文件中,再在64位操作系統(tǒng)下讀取,直接將內(nèi)存付給這個(gè)結(jié)構(gòu)體,就會(huì)出現(xiàn)問(wèn)題。

再比如我使用上面的結(jié)構(gòu)體編譯一個(gè)C++程序,直接將該結(jié)構(gòu)體對(duì)應(yīng)的內(nèi)存發(fā)送給一個(gè)Java程序,Java程序在讀取這段數(shù)據(jù)的時(shí)候就麻煩了。

所以為了避免內(nèi)存對(duì)齊,我建議自己定義數(shù)據(jù),顯式的將結(jié)構(gòu)體中的數(shù)據(jù)按照既定的規(guī)則寫(xiě)到數(shù)據(jù)流中。雖然這樣可以避免內(nèi)存對(duì)齊,但是大家也應(yīng)該了解一下內(nèi)存對(duì)齊。

內(nèi)存對(duì)齊和編譯器有關(guān)。

編譯器有自己的默認(rèn)“對(duì)齊系數(shù)”(也叫對(duì)齊模數(shù))。程序員可以通過(guò)預(yù)編譯命令#pragma
pack(n),n=1,2,4,8,16來(lái)改變這一系數(shù),其中的n就是你要指定的“對(duì)齊系數(shù)”。

VS2008的對(duì)齊系數(shù)默認(rèn)為8。

舉例說(shuō)明:

struct 
Test

{

    char  a;

    short  b;

    int c;

};

int main()

{

    Test 
    test;

    test.a = 0x12;

    test.b = 0x1234;

    test.c = 0x12345678;

    int size = sizeof(Test);

   Test *point = &test;

   return 0;

}

運(yùn)行之后得到:

size8

內(nèi)存排列方式為:

 

 
 

因?yàn)槲业碾娔X的CPUintel的,所以在內(nèi)存中小端存儲(chǔ),也就是你看到的c是按照byte倒敘存儲(chǔ)的(CPU大小端問(wèn)題將會(huì)在以后的章節(jié)中詳細(xì)說(shuō)明)

但是在中間有一byte的空白內(nèi)存,這就是編譯器內(nèi)存對(duì)齊造成的。

而如果數(shù)據(jù)結(jié)構(gòu)是這樣的(ac的順序變了):

struct 
Test

{

    char a;

    int c;

    short b;

};

運(yùn)行之后的結(jié)果是:

size的值為12

內(nèi)存的排列方式為:

 
 

 

內(nèi)存對(duì)齊的規(guī)則:

VS2008默認(rèn)#pragma pack(n)中的n=8

struct 
Test

{

char a; n=8 char=1 , 對(duì)齊起始地址為1的倍數(shù),所以a的起始內(nèi)存地址為0,內(nèi)存區(qū)間[0,0]

short b; n=8 short=2, 對(duì)齊起始地址為2的倍數(shù),所以b的起始內(nèi)存地址為2,內(nèi)存區(qū)間[2,3]

int c; n=8 int=4, 對(duì)齊起始地址為4的倍數(shù),所以b的起始內(nèi)存地址為4,內(nèi)存區(qū)間[4,7]

};

#pragma 
pack(1)

struct 
Test

{

char a; n=1 char=1 ,對(duì)齊起始地址為1的倍數(shù),所以a的起始內(nèi)存地址為0,內(nèi)存區(qū)間[0,0]

short b; n=1 short=2,對(duì)齊起始地址為1的倍數(shù),所以b的起始內(nèi)存地址為1,內(nèi)存區(qū)間[1,2]

int c; n=1 int=4, 對(duì)齊起始地址為1的倍數(shù),所以b的起始內(nèi)存地址為3,內(nèi)存區(qū)間[3,6]

};

還存在一種情況:

VS2008默認(rèn)#pragma pack(n)中的n=8

struct 
Test

{

double e;

char f;

};

int size =sizeof(Test); size的值為16   (注:補(bǔ)齊,保證最終大小是8的倍數(shù))

#pragma 
pack(4)

struct 
Test

{

double e;

char f;

};

int size =sizeof(Test); size的值為12  (注:補(bǔ)齊,保證最終大小是4的倍數(shù))

上面兩種情況的內(nèi)存排列是一致的,但是大小是不一樣的。

據(jù)說(shuō)GCCVS2008是不一樣的,沒(méi)有測(cè)試

下一次有時(shí)間試一下。

對(duì)于內(nèi)存對(duì)齊的問(wèn)題,我的建議就是顯式組織數(shù)據(jù),尤其對(duì)于網(wǎng)絡(luò)數(shù)據(jù)傳輸和讀寫(xiě)文件,不要直接取地址。

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    亚洲伦片免费偷拍一区| 91超精品碰国产在线观看| 在线亚洲成人中文字幕高清| 日本少妇aa特黄大片| 久久福利视频视频一区二区| 日韩18一区二区三区| 亚洲五月婷婷中文字幕| 开心久久综合激情五月天| 中文字幕日产乱码一区二区| 欧美激情一区二区亚洲专区| 亚洲精品福利视频你懂的| 久久精品国产99国产免费| 日韩一级毛一欧美一级乱| 天堂网中文字幕在线视频| 国产精品日韩欧美一区二区| 国产一级精品色特级色国产| 国产日韩欧美一区二区| 国产精品免费福利在线| 伊人国产精选免费观看在线视频| 亚洲视频在线观看你懂的| 国产精品一区二区传媒蜜臀| 日本一二三区不卡免费| 丰满人妻一二三区av| 国产精品一区二区三区欧美| 免费久久一级欧美特大黄孕妇| 草草夜色精品国产噜噜竹菊| 99久久国产精品成人观看| 国产精品久久女同磨豆腐| 福利视频一区二区在线| 午夜国产成人福利视频| 黄色三级日本在线观看| 尤物久久91欧美人禽亚洲| 午夜成年人黄片免费观看| 日本人妻精品中文字幕不卡乱码| 国产亚洲欧美一区二区| 欧美成人精品一区二区久久| 久久国产精品亚州精品毛片| 日韩综合国产欧美一区| 国产一级精品色特级色国产| 国产超薄黑色肉色丝袜| 夫妻性生活黄色录像视频|