字節對齊與大端小端與內存區域劃分

字節對齊

C語言字節對齊
C語言字節對齊/7213465

一、原則:

1.結構體內成員按自身按自身長度自對齊。

自身長度,如char=1,short=2,int=4,double=8,。所謂自對齊,指的是該成員的起始位置的內存地址必須是它自身長度的整數倍。如int只能以0,4,8這類的地址開始


2.結構體的總大小為結構體的有效對齊值的整數倍

結構體的有效對齊值的確定:

1)當未明確指定時,以結構體中最長的成員的長度為其有效值

2)當用#pragma pack(n)指定時,以n和結構體中最長的成員的長度中較小者為其值。

3)當用__attribute__ ((__packed__))指定長度時,強制按照此值為結構體的有效對齊值

二、例子

1。

struct AA{

   char a;

   int b;

   char c; 

}aa

結果,sizeof(aa)=12

何解?首先假設結構體內存起始地址為0,那么地址的分布如下

0  a

1  

2

3

4  b

5  b

6  b

7  b

8  c

9

10

11

char的字對齊長度為1,所以可以在任何地址開始,但是,int自對齊長度為4,必須以4的倍數地址開始。所以,盡管1-3空著,但b也只能從4開始。再加上c后,整個結構體的總長度為9,結構體的有效對齊值為其中最大的成員即int的長度4,所以,結構體的大小向上擴展到12,即9-11的地址空著。


2.


struct AA{
   char a;
char c; 
   int b;    
}aa
sizeof(aa)=8,為什么呢
0  a
1  c
2
3
4  b
5  b
6  b
7  b
因為c為char類型,字對齊長度為1,所以可以有效的利用1-3間的空格。看見了吧,變量定義的位置的不同時有可能影響結構體的大小的哦!

3.
#pragma pack(2)
struct AA{
   char a;
   int b;
   char c; 
}aa
sizeof(aa)=10,
為什么呢?a到c只占9字節長度,因為結構體的有效對齊長度在pack指定的2和int的4中取
較小的值2。故取2的倍數10。
如果當pack指定為8呢?那就仍然按4來對齊,結果仍然是12。


4.
struct AA{
   char a;
   int b;
   char c; 
}__attribute__((__8__))aa
sizeof(aa)=16,)
為咩?其實a到c仍然只占9字節長度,但結構體以8對齊,故取8的倍數16.
如果其指定2,則結果為10

如果pragma pack和__attribute__
同時指定呢?以__attribute__ 的為準。
需要說明的是,不管pragma
pack和__attribute__如何指定,結構體內部成員的自對齊仍然按照其自身的對齊值。

大端小端

字節序(大小端)詳解從高低地址和高低位開始理解(轉)

字節序(大小端)詳解從高低地址和高低位開始理解(轉)  


一、字節序定義
字節序,顧名思義字節的順序,再多說兩句就是大于一個字節類型的數據在內存中的存放順序(一個字節的數據當然就無需談順序的問題了)。
其實大部分人在實際的開發中都很少會直接和字節序打交道。唯有在跨平臺以及網絡程序中字節序才是一個應該被考慮的問題。
在所有的介紹字節序的文章中都會提到字節序分為兩類:Big-Endian和Little-Endian。引用標準的Big-Endian和Little-Endian的定義如下:
a) Little-Endian就是低位字節排放在內存的低地址端,高位字節排放在內存的高地址端。
b) Big-Endian就是高位字節排放在內存的低地址端,低位字節排放在內存的高地址端。
c) 網絡字節序:4個字節的32 bit值以下面的次序傳輸:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。這種傳輸次序稱作大端字節序。由于 TCP/IP首部中所有的二進制整數在網絡中傳輸時都要求以這種次序,因此它又稱作網絡字節序。比如,以太網頭部中2字節的“以太網幀類型”,表示后面數據的類型。對于ARP請求或應答的以太網幀類型來說,在網絡傳輸時,發送的順序是0x08,0x06。在內存中的映象如下圖所示:
棧底 (高地址)
---------------
0x06 -- 低位 
0x08 -- 高位
---------------
棧頂 (低地址)
該字段的值為0x0806。按照大端方式存放在內存中。
二、高/低地址與高低字節
首先我們要知道我們C程序映像中內存的空間布局情況:在《C專家編程》中或者《Unix環境高級編程》中有關于內存空間布局情況的說明,大致如下圖:
----------------------- 最高內存地址 0xffffffff
 | 棧底
 .
 .              棧
 .
  棧頂
-----------------------
 |
 |
\|/
NULL (空洞)
/|\
 |
 |
-----------------------
                堆
-----------------------
未初始化的數據
----------------(統稱數據段)
初始化的數據
-----------------------
正文段(代碼段)
----------------------- 最低內存地址 0x00000000
以上圖為例如果我們在棧上分配一個unsigned char buf[4],那么這個數組變量在棧上是如何布局的呢[注1]?看下圖:
棧底 (高地址)
----------
buf[3]
buf[2]
buf[1]
buf[0]
----------
棧頂 (低地址)
現在我們弄清了高低地址,接著來弄清高/低字節,如果我們有一個32位無符號整型0x12345678(呵呵,恰好是把上面的那4個字節buf看成一個整型),那么高位是什么,低位又是什么呢?其實很簡單。在十進制中我們都說靠左邊的是高位,靠右邊的是低位,在其他進制也是如此。就拿 0x12345678來說,從高位到低位的字節依次是0x12、0x34、0x56和0x78。
高低地址和高低字節都弄清了。我們再來回顧一下Big-Endian和Little-Endian的定義,并用圖示說明兩種字節序:
以unsigned int value = 0x12345678為例,分別看看在兩種字節序下其存儲情況,我們可以用unsigned char buf[4]來表示value:
Big-Endian: 低地址存放高位,如下圖:
棧底 (高地址)
---------------
buf[3] (0x78) -- 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) -- 高位
---------------
棧頂 (低地址)
Little-Endian: 低地址存放低位,如下圖:
棧底 (高地址)
---------------
buf[3] (0x12) -- 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) -- 低位
---------------
棧頂 (低地址)
在現有的平臺上Intel的X86采用的是Little-Endian,而像Sun的SPARC采用的就是Big-Endian。
三、例子
嵌入式系統開發者應該對Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU對操作數的存放方式是從低字節到高字節,而Big-endian模式對操作數的存放方式是從高字節到低字節。
例如,16bit寬的數0x1234在Little-endian模式CPU內存中的存放方式(假設從地址0x4000開始存放)為:
內存地址  存放內容
 0x4001    0x12
 0x4000    0x34
而在Big-endian模式CPU內存中的存放方式則為:
內存地址  存放內容
 0x4001    0x34
 0x4000    0x12
 
32bit寬的數0x12345678在Little-endian模式CPU內存中的存放方式(假設從地址0x4000開始存放)為:
內存地址  存放內容
 0x4003     0x12
 0x4002     0x34
 0x4001     0x56
 0x4000     0x78
 
而在Big-endian模式CPU內存中的存放方式則為:
內存地址  存放內容
 0x4003     0x78
 0x4002     0x56
 0x4001     0x34
 0x4000     0x12

整合字節對齊+大端小端+程序內存數據區域劃分

整合字節對齊+大端小端+程序數據區域劃分

內存分布

------高地址------


  • 棧又稱堆棧, 是用戶存放程序臨時創建的局部變量,也就是說我們函數括弧“{}”中定義的變量(但不包括static聲明的變量,static意味著在數據段中存放變量)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,并且待到調用結束后,函數的返回值也會被存放回棧中。由于棧的先進先出特點,所以棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的內存區。

  • 堆是用于存放進程運行中被動態分配的內存段,它的大小并不固定,可動態擴張或縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)
  • BBS
    BSS段(bss segment)通常是指用來存放程序中未初始化,或初始化為0的全局變量,靜態局部變量的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬于靜態內存分配。
  • 數據
    數據段(data segment)通常是指用來存放程序中已初始化為非0的全局變量的一塊內存區域。數據段屬于靜態內存分配。
  • 代碼段(code segment/text segment)通常是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經確定,并且內存區域通常屬于只讀, 某些架構也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數變量,例如字符串常量等。

------低地址------

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容