C語言深度解剖讀書筆記 3 結構體中記憶體對齊問題

2021-08-27 14:31:18 字數 1835 閱讀 1164

很多人都覺得記憶體對齊這個問題很難,很不好算,總算錯,其實我想說只要你畫一畫就沒那麼難了。好了,進入正題。

1.結構體為什麼要記憶體對齊(也叫位元組對齊):

其實我們都知道,結構體只是一些資料的集合,它本身什麼都沒有。我們所謂的結構體位址,其實就是結構體第乙個元素的位址。這樣,如果結構體各個元素之間不存在記憶體對齊問題,他們都挨著排放的。對於32位機,32位編譯器(這是目前常見的環境,其他環境也會有記憶體對齊問題),就很可能操作乙個問題,就是當你想要去訪問結構體中的乙個資料的時候,需要你操作兩次資料匯流排,因為這個資料卡在中間,如圖:

在上圖中,對於第2個short資料進行訪問的時候,在32位機器上就要操作兩次資料匯流排。這樣會非常影響資料讀寫的效率,所以就引入了記憶體對齊的問題。

2.記憶體對齊的規則:

a.第乙個成員起始於0偏移處

b.每個成員按其型別大小和指定對齊引數n中較小的乙個進行對齊

c.結構體總長度必須為所有對齊引數的整數倍

d.對於陣列,可以拆開看做n個陣列元素

3.來幾個小例子,畫畫圖,有助於理解:

第乙個例子,**如下:

#include struct _tag_str1

str1;

struct _tag_str2

str2;

int main()

輸出的結果分別是:str1為12 str2為8,分析的過程如下圖:

看圖很自然就知道了str1為12個位元組,str2為8個位元組。

第二個例子,上面的那個例子有好多問題還沒有考慮到,比如說上面的那個例子在8位元組對齊,和4位元組對齊的情況都是一樣的。結構體中巢狀結構體的記憶體對齊怎麼算,所以就有了這個例子,**如下:

#include #pragma pack(8)

//#pragma pack(4)

struct s1

;struct s2

;#pragma pack()

int main()

在dev c++中,預設的是8位元組對齊。我們分析下在4位元組對齊的情況下輸出的是,s2是20,s1是8,分析如圖:

在4位元組對齊的情況中,有乙個問題值得注意:就是圖中畫1的地方。這裡面本應short是可以上去的。但是對於結構體中的結構體一定要十分警惕,s1是一體的,short已經由於long進行了記憶體對齊,後面還空了兩個位元組的記憶體,其實此時的short已經變成了4個位元組了!!!即結構體不可拆,不管是多少位元組對齊,他們都是一體的。所有的圈都變成了叉。所以說結構體只能往前篡位置,不能改變整體。

我們在分析一些8位元組對齊的情況,如圖:

同樣,到這裡又有乙個位元組對齊的原則要好好重申一下:就是以什麼為對齊引數,首先我們要知道編譯器或者自己定義的是多少位元組對齊的,這個數為n。然後我們要看這個結構體中的各個資料型別,找到所佔位元組數最大的型別,為m。如果n大於m,就以m為對齊引數,比如說乙個4位元組對齊的結構體中都是short,那這個結構體以什麼為對齊引數,當然是2了,如果m大於n,就以n為對齊引數,比如說在4位元組對齊的情況下的double型別。

以上就是我對記憶體對齊的小總結,最最想要說明的就是兩大段紅色的部分。

C語言深度解剖讀書筆記3

int p null 和 p null 的區別int p null 可以通過偵錯程式檢視p的值為 0x00000000 這句 的意思是 定義乙個指標變數p,其指向的記憶體裡面儲存的是 int 型別的資料 在定義變數p的同時把p的值設定為 0x00000000,而不是把 p 的值設定為0x000000...

讀書筆記《c語言深度解剖》 4

10.struct關鍵字 這裡struct關鍵字講解得比較少,主要有3點 1 空結構體的大小為1 在gcc下我的輸出是0 2 柔性陣列 在c99中,允許結構最後乙個元素是乙個大小未確定的陣列,這個陣列叫做柔性陣列。但是柔性陣列前面必須至少有乙個其他成員。用sizeof返回結構體大小的時候,並不包含柔...

C語言深度解剖讀書筆記1

關鍵字 意義關鍵字 意義auto 宣告自動變數,預設時編譯器一般預設為auto register 宣告暫存器變數 int宣告整型變數 const 宣告唯讀變數 double 宣告雙精度變數 volatile 說明變數在程式執行中可被隱含地改變 long 宣告長整型變數 typedef 用以給資料型別...