最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入內(nèi)存對齊的詳解

 更新時間:2013年05月13日 09:46:15   作者:  
本篇文章是對內(nèi)存對齊進行了詳細的分析介紹,需要的朋友參考下

1.引子

    在結構中,編譯器為結構的每個成員按其自身的自然對界(alignment)條件分配空間。各個成員按照它們被聲明的順序在內(nèi)存中順序存儲,第一個成員的地址和整個結構的地址相同。

    例如,下面的結構各成員空間分配情況(假設對齊方式大于2字節(jié),即#pragma pack(n), n = 2,4,8...下文將討論#pragmapack()):

復制代碼 代碼如下:

struct test
{
     char x1;
     short x2;
     float x3;
     char x4;
};

    結構的第一個成員x1,其偏移地址為0,占據(jù)了第1個字節(jié)。第二個成員x2為short類型,其起始地址必須2字節(jié)對界,即偏移地址是2的倍數(shù)。因此,編譯器在x2和x1之間填充了一個空字節(jié),將x2放在了偏移地址為2的位置。結構的第三個成員x3和第四個成員x4恰好落在其自然對界地址上,在它們前面不需要額外的填充字節(jié)。在test結構中,成員x3要求4字節(jié)對界,是該結構所有成員中要求的最大對界單元,因而test結構的自然對界條件為4字節(jié),整個結構體的大小是最大對界單元大小的整數(shù)倍(結構體內(nèi)部有結構體時也遵循這個規(guī)則,下文將提到),編譯器在成員x4后面填充了3個空字節(jié)。整個結構所占據(jù)空間為12字節(jié)。
    關于為什么要內(nèi)存對齊,參考<解析內(nèi)存對齊 Data alignment: Straighten up and fly right的詳解>??戳诉@篇文章便可以更輕松的理解下面的內(nèi)容。

    好了,下面說說#pragma pack:

2.#pragma pack()

    該預處理指令用來改變對齊參數(shù)。在缺省情況下,C編譯器為每一個變量或數(shù)據(jù)單元按其自然對界條件分配空間。一般地,可以通過下面的方法來改變?nèi)笔〉膶R參數(shù):

     · 使用偽指令#pragma pack (n),C編譯器將按照n字節(jié)對齊。

     · 使用偽指令#pragma pack (),取消自定義字節(jié)對齊方式。

也可以寫成:

#pragma pack(push,n)

#pragma pack(pop)

#pragma pack (n)表示每個成員的對齊單元不大于n(n為2的整數(shù)次冪)。這里規(guī)定的是上界,只影響對齊單元大于n的成員,對于對齊字節(jié)不大于n的成員沒有影響。其實從字面意思,pack是“包裹,打包”的意思,#pragma pack(n)規(guī)定n個字節(jié)是一個“包裹”,個人認為實在不理解的話可以認為處理器一次性可以從內(nèi)存中讀/寫n個字節(jié),這樣好理解。對于大小小于n的成員,當然是按照自己的對齊條件對齊,因為不論怎么放都可以一次性取出。對于對齊條件大于n個字節(jié)的成員,成員按照自身的對齊條件對齊和按照n字節(jié)對齊需要相同的讀取次數(shù),但按照n字節(jié)對齊節(jié)省空間,何樂而不為呢??梢詤⒖嘉疑厦嫣岬降?lt;解析內(nèi)存對齊 Data alignment: Straighten up and fly right的詳解>。下面是一位大牛的觀點,和我說的是一個意思:

   All it means is that each member of it will require alignment no greater than n.It doesn't mean that each member will have alignment requirement n.Notice, after all, it's called pack and not align for a reason-- precisely because it controls packing, not alignment.

另外,GNU C還有如下的一種方式:

     · __attribute__((aligned (n))),讓所作用的結構成員對齊在n字節(jié)自然邊界上。如果結構中有成員的長度大于n,則按照最大成員的長度來對齊。

     · __attribute__ ((packed)),取消結構在編譯過程中的優(yōu)化對齊,按照實際占用字節(jié)數(shù)進行對齊。

以上的n = 1, 2, 4, 8, 16... 第一種方式較為常見。

3.結構體內(nèi)成員如何找出自己的位置

首先遵循以下規(guī)則:

1.  每個成員分別取自己的對齊方式和#pragma pack指定的對齊參數(shù)二者的較小值作為自己的對齊方式。

2.  復雜類型(如結構)的對齊方式是該類型聲明時所使用的對齊方式,或者說是聲明時它的所有成員使用的對齊參數(shù)的最大值,最后和此時的#pragma pack指定的對齊參數(shù)二者取極小值。大牛是這么說的:

The documentation for #pragma pack(n) says that "The alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member,whichever is smaller". However I think this is incorrect; the docs should say that the alignment of a member will be on a boundary that is either a multiple of n or the alignment requirement of the member, whichever is smaller.

3.  對齊后的長度必須是成員中最大的對齊參數(shù)(不是成員的大小)的整數(shù)倍,這樣在處理數(shù)組時可以保證每一項都邊界對齊。

4.  對于數(shù)組,比如:char a[3];這種,它的對齊方式和分別寫3個char是一樣的。也就是說它還是按1個字節(jié)對齊.

        如果寫: typedef char Array3[3];

        Array3這種類型的對齊方式還是按1個字節(jié)對齊,而不是按它的長度。

5.  不論類型是什么,對齊的邊界一定是1,2,4,8,16,32,64....中的一個。

看一個簡單的例子:

復制代碼 代碼如下:

#pragma pack(8)
struct s1
{
    short a;
    long b;
};
struct s2
{
    char c;
    s1 d;
    long long e;
};
#pragma pack()

    成員對齊有一個重要的條件:每個成員分別對齊。即每個成員按自己的方式對齊.

    也就是說上面雖然指定了按8字節(jié)對齊,但并不是所有的成員都是以8字節(jié)對齊。其對齊的規(guī)則是,每個成員按其類型的對齊參數(shù)(通常是這個類型的大小)和指定對齊參數(shù)(這里是8字節(jié))中較小的一個對齊。并且結構的長度必須為所用過的所有對齊參數(shù)的整數(shù)倍(只要是最大的對齊參數(shù)的整數(shù)倍即可),不夠就補空字節(jié)(視編譯器而定)。

    S1中,成員a是2字節(jié)默認按2字節(jié)對齊,指定對齊參數(shù)為8,這兩個值中取2,a按2字節(jié)對齊;成員b是4個字節(jié),默認是按4字節(jié)對齊,這時就按4字節(jié)對齊,a后補2個字節(jié)后存放b,所以sizeof(S1)應該為8。8是4的倍數(shù),滿足上述的第3條規(guī)則。

    S2中,c和S1中的a一樣,按2字節(jié)對齊,而d是個結構,它是8個字節(jié),它按什么對齊呢?對于結構來說,它的默認對齊方式就是該結構定義(聲明)時它的所有成員使用的對齊參數(shù)中最大的一個,S1的是4,小于指定的8。所以成員d就是按4字節(jié)對齊,c后補2個字節(jié),后面是8個字節(jié)的結構體d。成員e是8個字節(jié),它是默認按8字節(jié)對齊,和指定的一樣,所以它對到8字節(jié)的邊界上,這時,已經(jīng)使用了12個字節(jié)了,所以d后又補上4個字節(jié),從第16個字節(jié)開始放置成員e。這時,長度為24,已經(jīng)可以被最大對齊參數(shù)8(成員e按8字節(jié)對齊)整除。這樣,一共使用了24個字節(jié)。

   上面的不夠復雜?再來一個:

復制代碼 代碼如下:

#pragma pack(4)
struct s1
{
    char a;
    double b;
};
#pragma pack()

#pragma pack(2)
struct s2
{
    char c;
    struct s1 st1;
};
#pragma pack()

 
#pragma pack(2)
struct s3
{
    char a;
    long b;
};
#pragma pack()

#pragma pack(4)
struct s4
{
    char c;
    struct s3 st3;
};
#pragma pack()

    先看s1,a放在偏移地址為0的位置(第一個字節(jié))。b默認8字節(jié)對齊,但指定對齊參數(shù)是4字節(jié),所以b按4字節(jié)對齊,放在偏移地址為4的位置,a后補3個字節(jié)。所以sizeof(s1)是12。結構體s1的對齊參數(shù)是4,下面會用到。

    再看s2,c放在第一個字節(jié)。st1自己的對齊參數(shù)是4,但此時指定的對齊參數(shù)是2,所以st1按照2字節(jié)對齊,c后補一個字節(jié)后存放st1。注意,st1內(nèi)部是不會變的,聲明s1時是什么樣就是什么樣,因為我們要保證sizeof(s2.st1) == sizeof(s1),如果不這樣就亂套了。這樣sizeof(s2)是14。結構體s2的對齊參數(shù)是2,14是2的整數(shù)倍。

    再看s3,a放在第一個字節(jié)。b默認4字節(jié)對齊,但指定的對齊參數(shù)是2,所以b按2字節(jié)對齊,放在偏移地址為2的位置,a后補一個字節(jié)。sizeof(s3)是6。結構體s3的對齊參數(shù)是2(后面會用到),6是2的整數(shù)倍。

    最后看s4,c放在第一個字節(jié)。st3自己的對齊參數(shù)是2,指定的對齊參數(shù)是4,所以st3取極小值,按2字節(jié)對齊,放在偏移地址為2的位置,c后補一個字節(jié)。sizeof(s4)是8,結構體的對齊參數(shù)是2,8是2的整數(shù)倍。

相關文章

  • C++ 空指針解引用的解決方法

    C++ 空指針解引用的解決方法

    空指針解引用是一種常見且嚴重的錯誤,它通常由于指針未初始化、被設置為nullptr或指向無效地址引起,本文主要介紹了C++ 空指針解引用的解決方法,感興趣的可以了解一下
    2024-08-08
  • C語言全面細致精講操作符的使用

    C語言全面細致精講操作符的使用

    C?語言提供了豐富的操作符,有:算術操作符,移位操作符,位操作符,賦值操作符,單目操作符,關系操作符,邏輯操作符,條件操作符等。接下了讓我們詳細了解掌握它
    2022-05-05
  • 詳解計數(shù)排序算法及C語言程序中的實現(xiàn)

    詳解計數(shù)排序算法及C語言程序中的實現(xiàn)

    技術排序算法與我們普通接觸的冒泡排序和快速排序等基于元素比較的算法不同,在編程中通過C語言的數(shù)組能夠清除地表達出來,這里我們就來詳解計數(shù)排序算法及C語言程序中的實現(xiàn)
    2016-07-07
  • C語言函數(shù)指針數(shù)組實現(xiàn)計算器功能

    C語言函數(shù)指針數(shù)組實現(xiàn)計算器功能

    這篇文章主要通過C語言函數(shù)指針數(shù)組實現(xiàn)了計算器的功能,是一個很好而且流程詳細的小例子,感興趣的新手朋友們可以自己動手也寫一遍
    2022-04-04
  • C++中std::deque的使用

    C++中std::deque的使用

    std::deque是C++標準庫中的一個雙端隊列容器,本文主要介紹了C++中std::deque的使用,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • C++?多線程編程pthread的基本使用詳解

    C++?多線程編程pthread的基本使用詳解

    在C++開發(fā)中,原生的線程庫主要有兩個,一個是C++11提供的<thread>(std::thread類),另一個是Linux下的<pthread.h>(p_thread類),本文主要介紹pthread的基本使用方式,需要的朋友可以參考下
    2024-05-05
  • 數(shù)據(jù)結構之位圖(bitmap)詳解

    數(shù)據(jù)結構之位圖(bitmap)詳解

    這篇文章主要介紹了數(shù)據(jù)結構之位圖詳解,本文講解了位圖的基本知識、位圖的實現(xiàn)方法、位圖的應用等內(nèi)容,需要的朋友可以參考下
    2014-08-08
  • C語言時間函數(shù)之mktime和difftime詳解

    C語言時間函數(shù)之mktime和difftime詳解

    這篇文章主要為大家詳細介紹了C語言時間函數(shù)之mktime和difftime,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一,希望能夠給你帶來幫助
    2022-02-02
  • C++ Easylogging++日志庫配置使用超詳細講解

    C++ Easylogging++日志庫配置使用超詳細講解

    這篇文章主要介紹了C++ Easylogging++日志庫配置使用,Easylogging++是用于C++應用程序的單頭高效日志庫。它非常強大,高度可擴展并且可以根據(jù)用戶的要求進行配置
    2022-11-11
  • C/C++程序開發(fā)中實現(xiàn)信息隱藏的三種類型

    C/C++程序開發(fā)中實現(xiàn)信息隱藏的三種類型

    這篇文章主要介紹了C/C++程序開發(fā)中實現(xiàn)信息隱藏的三種類型的相關資料,需要的朋友可以參考下
    2016-02-02

最新評論

垫江县| 克什克腾旗| 九寨沟县| 威远县| 囊谦县| 库伦旗| 青浦区| 沭阳县| 阿城市| 大兴区| 固始县| 永胜县| 徐闻县| 镇沅| 浙江省| 育儿| 大冶市| 电白县| 龙里县| 苍山县| 宜良县| 肃宁县| 新蔡县| 康保县| 大英县| 莫力| 怀集县| 南丹县| 额尔古纳市| 云南省| 东宁县| 镇坪县| 涟水县| 黑河市| 石门县| 宝鸡市| 内黄县| 玛多县| 诸城市| 长葛市| 岑溪市|