1. 程式人生 > >結構體中的對齊與補齊!

結構體中的對齊與補齊!

    申請blog已經很長時間了,一直沒有時間往上寫點內容,正巧最近各種巧合需要重新學習一下Linux下的開發,將好久不用的C\C++重新研究了一通,在這裡就把一些我自己搞弄清楚的點寫一下,一來為了鞏固一下,二來給需要的朋友看一看,寫的不好請多指教。

    關於結構體,從第一次接觸structure時就對它感到十分驚訝,因為這是一種真正讓你自己定義的型別,它將一系列相關的成員集合在一起,然後逐個去處理。如何形容這種感覺呢?很美妙!所以今天我來說一下最近總結的結構體中對齊與補齊的問題。

    首先我們來看下面的這段關於商品的結構體定義,通過sizeof(gs)我們最終可以得到這個結構體的位元組數是40!那麼它是如何算出來的呢?

typedef struct Goods{
char name[18];
double price;
char special;
int num;
short saled;
}gs;

    結構體的位元組數應當包含了內部所有成員位元組數之和,那麼是否將內部各成員的位元組數相加在一起就可以嗎?我們來試一下,18+8+1+4+2=33?和答案40不一致吧!因此上述的想法顯然是錯誤的,所以這裡我就來說一下對齊的定義。

    所謂的對齊,其實是指在結構體當中某個成員變數的儲存地址是本身佔用位元組數的倍數。吧啦吧啦~~什麼亂七八糟的。。。好吧我來給你們解釋一下(明白的大神就繞過我吧!)。這裡要事先做一個說明,變數本身位元組數的倍數說白了就是char位元組數為1,那麼起始地址就是1的倍數才可以,int是4所以就得是4的倍數,但是如果本身位元組數超過了4,那麼仍然按照4來計算,就譬如double本身是8但是在對齊的過程中要按照4來計算,好吧也許你還不明白,那就舉個例子。

    假設我們定義了一個結構體變數a,即gs a;它的起始地址是2000,而name本身所佔的位元組數又是18,所以第一個成員name的結束地址為2018,下一個成員price是double型別了,其本身所佔位元組數為8明顯超過了4,所以按照4來計算,而2018明顯不是4的倍數,這就需要我們補充2個位元組將其變為2020成為4的倍數,同理結束地址會變為2028,2028是special位元組數的倍數,所以就可以直接在末尾新增也就是2029,同理num的的首地址要變為2032,某地址為2036。好到這裡基本的對齊邏輯就講完了,所以接著往下看。

    當我們計算到num的2036後按道理其本身是saled位元組數的倍數,所以直接在末尾新增即可,但是你最終發現新增後的末地址變成了38?what?不是說好的40嘛?別急這就是補齊的意義了!

    為什麼要補齊?

    上述情況下我們僅僅定義了一個變數a,但是假如我們同時定義兩個變數a,b,在記憶體空間上,a與b是需要緊靠排列的,也就說如果不補齊那麼就需要緊接著上面的2038往下排,而本身a與b的內部分佈應該是相同的,也就是說b內部各成員直接的空隙相同,這就造成了一個問題,你會發現b根本無法對齊記憶體地址。所以才有了補齊這種做法,所謂的補齊就是補齊成最大成員的倍數!也就是末地址要是最大成員的倍數,因此就是2040,這也是為什麼答案是40個位元組的原因了!

    以上是對於對齊與補齊的個人介紹,還請多多指教。