日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ 内存对齐

發(fā)布時間:2023/12/2 c/c++ 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 内存对齐 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

注:本文代碼測試環(huán)境為win7 X64 cpu, 編譯器為gcc4.7.1 和 vs2010

?

內(nèi)存對齊是編譯器為了便于CPU快速訪問而采用的一項技術(shù)

我們先從一個例子開始,對下面的類(或者結(jié)構(gòu)體)

class node

{

char c;

int i;

short s;

}no;

sizeof(no)的值是多少呢,如果你的回答是7(1+4+2),那么你應(yīng)該認真閱讀下面的內(nèi)容。可以在編譯器上試試,輸出的結(jié)果是12,這就是內(nèi)存對齊的結(jié)果。

?

為什么要進行內(nèi)存對齊呢?

  • 平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù)的;某些硬件平臺只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常。
  • 性能原因:數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問;而對齊的內(nèi)存訪問僅需要一次訪問。???????????????????????????????????????????????????????????????????????本文地址
  • 編譯器一般按照幾個字節(jié)對齊呢?本文中兩個編譯器默認按照類中最大類型長度來對齊,我么也可以使用語句#pragma pack(i)(i = 1,2,4,8,16)來設(shè)置對齊字節(jié)數(shù)目,vs還可以在項目屬性-配置屬性-c/c++-代碼生成-結(jié)構(gòu)成員對齊設(shè)置。

    ?

    對齊規(guī)則如下:

  • 如果設(shè)置了內(nèi)存對齊為 i 字節(jié),類中最大成員對齊字節(jié)數(shù)為j,那么整體對齊字節(jié)n = min(i, j)? (某個成員的對齊字節(jié)數(shù)定義:如果該成員是c++自帶類型如int、char、double等,那么其對齊字節(jié)數(shù)=該類型在內(nèi)存中所占的字節(jié)數(shù);如果該成員是自定義類型如某個class或者struct,那個它的對齊字節(jié)數(shù) = 該類型內(nèi)最大的成員對齊字節(jié)數(shù)《詳見實例4》)
  • 每個成員對齊規(guī)則:類中第一個數(shù)據(jù)成員放在offset為0的位置;對于其他的數(shù)據(jù)成員(假設(shè)該數(shù)據(jù)成員對齊字節(jié)數(shù)為k),他們放置的起始位置offset應(yīng)該是 min(k, n) 的整數(shù)倍
  • 整體對齊規(guī)則:最后整個類的大小應(yīng)該是n的整數(shù)倍
  • 當設(shè)置的對齊字節(jié)數(shù)大于類中最大成員對齊字節(jié)數(shù)時,這個設(shè)置實際上不產(chǎn)生任何效果(實例2);當設(shè)置對齊字節(jié)數(shù)為1時,類的大小就是簡單的把所有成員大小相加
  • 我們通過以下幾個實例來分析

    實例1:(沒有指定對齊字節(jié),則n = 最大成員(int i)的大小4)

    class node

    {

    char c;?? //放在位置0,位置區(qū)間[0]

    int i;????? //4 = n, 那么放置起始位置應(yīng)該是4的倍數(shù),即4,位置區(qū)間為[4~7]

    short s; //2 < n,那么放置起始位置應(yīng)該是2的倍數(shù),即8,位置區(qū)間為[8~9]

    }

    此時成員共占用[0~9]10個字節(jié),還要整體對齊,大小應(yīng)該是4的倍數(shù),即12

    ?

    實例2:(假設(shè)指定對齊字節(jié)為8,那么n = min(8,4) = 4)

    class node

    {

    int i; //放在位置0,位置區(qū)間[0~3]

    char c; //1 < n, 那么放置起始位置應(yīng)該是1的倍數(shù),即4,位置區(qū)間為[4]

    short s; //2 < n,那么放置起始位置應(yīng)該是2的倍數(shù),即6,位置區(qū)間為[6~7]

    }

    成員共占據(jù)[0~7]8個字節(jié),剛好是4的倍數(shù),因此大小是8

    ?

    實例3:(假設(shè)指定對齊字節(jié)是2,則n = min(2,4) = 2)

    class node

    {

    char c; //放在位置0,位置區(qū)間[0]

    int i; //4 > n, 那么放置起始位置應(yīng)該是2的倍數(shù),即2,位置區(qū)間為[2~5]

    short s; //2 = n,那么放置起始位置應(yīng)該是2的倍數(shù),即6,位置區(qū)間為[6~7]

    }

    此時成員共占用[0~7]8個字節(jié),剛好是4的倍數(shù),因此大小是8

    ?

    實例4:(按照默認設(shè)置)

    class temp?
    {?
    ??? char c;?
    ??? int i;?
    ??? short s1;?
    };

    由實例1可知,默認對齊情況下,temp的大小是12,temp的對齊字節(jié)數(shù)是:三個成員取最大的,即為4;

    對于node,n = 其三個成員對齊字節(jié)數(shù)取最大,即等于t的對齊字節(jié)數(shù),也就是 4。

    class node

    {

    char c; //放在位置0,位置區(qū)間[0]

    temp t; //4(temp的對齊字節(jié)數(shù)) = n, 那么放置起始位置應(yīng)該是4的倍數(shù),即4,位置區(qū)間為[4~15]

    short s; //2 < n,那么放置起始位置應(yīng)該是2的倍數(shù),即16,位置區(qū)間為[16~17]

    }

    此時成員共占用[0~17]18個字節(jié),還要整體對齊,大小應(yīng)該是4的倍數(shù),因此大小是20

    ?

    實例5:(默然設(shè)置)

    對于node,n = 其三個成員對齊字節(jié)數(shù)取最大,即等于d的對齊字節(jié)數(shù),也就是 8。

    class node

    {

    temp t; //放在位置0,位置區(qū)間[0~11]

    double d; //8(temp的對齊字節(jié)數(shù)) = n, 那么放置起始位置應(yīng)該是8的倍數(shù),即16,位置區(qū)間為[16~23]

    short s; //2 < n,那么放置起始位置應(yīng)該是2的倍數(shù),即24,位置區(qū)間為[24~25]

    }

    此時成員共占用[0~25]26個字節(jié),還要整體對齊,大小應(yīng)該是8的倍數(shù),因此大小是32.

    ?


    類繼承時的內(nèi)存對齊

    考慮如下類

    class A

    {

    int i;

    char c1;

    }

    class B:public A

    {

    char c2;

    }

    class C:public B

    {

    char c3;

    }

    sizeof(C)結(jié)果是多少呢,gcc和vs給出了不同的結(jié)果,分別是8、16

    gcc中:C相當于把所有成員i、c1、c2、c3當作是在一個class內(nèi)部,(先繼承后對齊)

    vs中:對于A,對齊后其大小是8;對于B,c2加上對齊后的A的大小是9,對齊后就是12;對于C,c3加上對齊后的B大小是13,再對齊就是16 (先對齊后繼承)

    關(guān)于c++對象繼承后的內(nèi)存布局,更詳細的分析可以《深度探索參考c++對象模型》第三章

    ?

    參考資料:

    zhyjunfov的ChinaUnix博客:gcc的內(nèi)存對齊

    【版權(quán)聲明】轉(zhuǎn)載請注明出處:http://www.cnblogs.com/TenosDoIt/p/3590491.html

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

    總結(jié)

    以上是生活随笔為你收集整理的C++ 内存对齐的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。