C語言熱門考點結構體與記憶體對齊詳解

2022-09-21 22:00:22 字數 2428 閱讀 9721

目錄

到底什麼是結構體內存對齊,我們用一段**來介紹一下

struct s1

;int main()

先來解釋s1,結構體s1中有2個char型別,1個int型別。那按道理應該是佔2*1+4=6個位元組啊,為什麼列印的是12呢?到這裡,我們必須要來了解一下結構體內存對齊的規則:

1.結構體的第乙個成員永遠放在結構體起始位置偏移量為0的位置

對於偏移量你可以這樣理解:陣列下標為0的相對它自己偏移量為0,下標為1的相對下標為0的偏移量為1…

舉例說明:

s1第乙個成員是c1,它會被放在結構體起始位置偏移量為0的位置,如下圖紅色部分

2.從第二個成員開始,總是放在偏移量為乙個對齊數的整數處,對齊數=編譯器預設的對齊數和www.cppcns.com變數自身大小的較小程式設計客棧值

對齊數=min(編譯器預設的對齊數,變數自身大小)

linux-沒有對齊數,vs下對齊數預設為8

我們仍以s1這個結構體進行舉例,結構體第二個成員是int型別的a,佔4個位元組,筆者vs環境下預設對齊數是8,取兩者較小值是4,那a應該放到偏移量為4的倍數上

放到4的倍數上也就說可以放在偏移量為4這裡,偏移量為1,2,3的這3個空間就白白被浪費了。而a是int型佔4個位元組,所以會一直占用到偏移量為7的位置。

接下來是結構體的第三個成員,char型別的c2,c2佔1個位元組,vs環境下預設對齊數是8,取較小值為1,也就是說只要是1的倍數的偏移量都可以放,我們緊接著放在a後面,也就是偏移量8的位置

那到這裡結構體3個成員都用完了啊,只有8個啊,為什麼列印是12呢?這裡就要涉及結構體內存對齊的第3個規則

3.結構體的總大小必須是各個成員的對齊數中最大的那個對齊數的整數倍

我們由前面講解知道結構體三個成員c1,a,c2對齊數分別為1,4,1這三個中最大對齊數是4,總大小要為4的整數倍,那這時候肯定有小夥伴會問:我們現在不是對齊到8了嘛,8不是4的倍數嗎?注意!這裡說的是空間總大小,而8是所謂的偏移量,偏移量是從0開始算的,到8已經有9個空間了,所以我們這裡空間要到12,也就是偏移量到11

(後面加上的三個空間用不到,但是由於規定還是算在結構體總空間內)

我們再來看一道類似的題目

**如下(示例):

struct s2

;int main()

首先第乙個結構體成員是char型別的c1,由規則1,它會直接被放在偏移量為0的位置

(圖示灰色部分)

第二個成員是char型別的c2,佔1位元組,vs下預設對齊數是8,取較小值是1,只要放在偏移量為1的倍數上即可(任意位置),緊跟著0,放在偏移量為1處(圖示紅色部分)

最後乙個成員int型別的a,佔4個位元組,vs環境下預設對齊數是8,取較小者4,放在偏移量為4的整數倍處,也就是4這裡,然後由於int佔4個位元組所以一直占用到偏移量7處

再來看看規則3,結構體的總大小必須是各個成員的對齊數中最大的那個對齊數的整數倍,也就是4的倍數,我們現在正好是佔8個空間,8正好是4的倍數,所以就不用再往下浪費空間了,列印出8

**如下(示例):

struct s3

;struct s4

;int main()

關於結構www.cppcns.com體s3我們可以採用和前面s1、s2一樣的方法計算出來是佔16個位元組空間,我們這裡重點討論s4,對s3有興趣的小夥伴可自行求解。

s4中的第乙個成員c1,按規則1直接放在偏移量為0處,第二個成員s3怎麼辦呢?這裡涉及結構體內存對齊的第四個規則:

如果巢狀了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數倍數處,結構體的整體大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍

s3這個結構體三個成員最大對齊數是8,也就是要對齊到偏移量為8的倍數處,然後s3是佔16個位元組,所以一直佔到偏移量23處(s3結構體對齊數是本身s3結構體三個成員中最大對齊數)

ps:在vs環境中,巢狀結構體的最大對齊數超過8,仍然用8做最大對齊數(比預設對齊數大了,取較小值就取預設對齊數了)

s4最後乙個成員double型別的d佔8位元組,預設對齊數8,對齊數取8,然後放在偏移量為對齊數的整數倍處,正好往下放在24處,本身佔8位元組所以佔到31

偏移量0-31共佔32位元組,s4中的成員c1,s3,d對齊數分別為1,8,8所以最大對齊數是8,32恰是8的倍數,所以這裡不用再浪費空間來滿足 「結構體的總大小必須是各個成員的對齊數中最大的那個對齊數的整數倍」這個規則,結構體總大小就是32

不是所有的硬體平台都能訪問任意位址上的任意資料的;某些硬體平台只能在某些位址處取某些特定的型別的資料,否則丟擲硬體異常

資料結構(尤其是棧),應盡可能地在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅僅需要1次

總體來說:結構體的記憶體對齊是用空間換時間

本文介紹了結構體內存對齊的四大規則,並舉例說明了如何進行方法的操作,對於其中特殊的巢狀結構體內存對齊也進行了相應講解,希望讀者在學習完本文後能對結構體內存對齊有乙個系統的認識。祝讀者學www.cppcns.com業有成!

C語言結構體對齊 記憶體對齊問題

c語言結構體對齊也是老生常談的話題了。基本上是面試題的必考題。內容雖然很基礎,但一不小心就會弄錯。寫出乙個struct,然後sizeof,你會不會經常對結果感到奇怪?sizeof的結果往往都比你宣告的變數總長度要大,這是怎麼回事呢?有人給對齊原則做過總結,具體在 看到現在已記不起來,這裡引用一下前人...

C語言結構體的記憶體對齊

學過c語言的大家應該都學到過結構體,結構體是一種聚合資料型別,它可以把不同型別的資料儲存在一起,我們把結構體中儲存的資料叫做結構體成員。了解了結構體後,我們來談一談結構體在計算機系統中是如何儲存的,首先,我們來看看下面這段 struct a int main 這段 中我們分別定義了三個結構體成員,按...

C語言結構體之記憶體對齊

首先看乙個例子,下面有乙個結構體 struct structtest1 假設這個結構體成員在記憶體中是緊湊排列的,那麼c1的儲存位址就是0,s的儲存位址是1 2,c2的儲存位址是3,i的儲存位址是4 7,c1的位址是0000000000000000,s的位址是0000000000000001,c2的...