此為“小紫”對sizeof的一些見解,是以發出來給大家分享下,發現網上對記憶體對齊的說法不統一,
是以才實驗了一下,得出來了一個“标準”。(我知道網上有很多比我這篇文章更具體,更詳細,但我會
努力把這篇文章寫得通俗易懂,讓大家更容易了解。另外,第五部分是我寫這篇文章的原因)
如果您有轉載的欲望,請您能夠保留這版權資訊。這是讀者們唯一可以信任的東西。(本篇文章在
WIN32平台下寫,是以位元組大小也以WIN32為标準)
本文首發至本人部落格中.
一、為什麼要讀這篇文章?
這篇文章面對初學者設計,通過這篇文章來了解記憶體中類型或變量所占位元組的“藝術”,如果覺
得本文太簡單,我可以推薦一篇文章:《詳細解析C語言中的sizeof》,本文有很多細節也是參考的那裡
。如果前幾個部分太簡單,可以從第五部分看起。
二、什麼是sizeof?
sizeof其實是一個操作符,而并非是一個函數,寫成“括号形式”(我把加“()”的任何語句
形式都叫“括号形式”)隻是它的一種普遍寫法。sizeof可以得到操作符所占用記憶體位元組數的大小。
sizeof操作符可以為變量、基本類型(int,float等都是基本類型)、結構體。
三、sizeof的格式
(1)對于變量有兩種格式:
①sizeof(變量);
②sizeof 變量;這種格式是允許的。但是不普遍。
(2)對于結構體和基本類型隻有一種寫法:
sizeof(結構名字、基本類型名);
四、注意!
不确定所占記憶體大小的類型(包括不确定大小的共用結構(聯合結構)等),void類型和函數等不可
以作為sizeof的操作符。sizeof的傳回值為size_t(也就是unsigned int)。指針的大小根據編譯器決定。
五、sizeof的結果
在開始正文之前,請大家看一個程式 段:
long double p[2]={0.0};
int abc(long double a[])
{
unsigned int fR=sizeof(a);
return fR;
}
那麼現在該告訴我,函數的傳回值是多少?
嗯,也許你會回答(隻是也許,我知道,這個世界上不乏有高手的存在),傳回值是12(一個
long double所占記憶體的位元組為12),但是函數卻傳回了4。其實,這是編譯器的一次“小惡作劇”,我們
都知道,編譯器有兩大任務:1.編譯成可執行檔案。2.優化代碼。但是編譯器為了簡化編譯,讓數組在傳
入函數的時候産生了意外,被當作了指針處理,以此來簡化編譯。是以結果傳回的是sizeof(long
double*).嗯~~如果你不相信的話,我可以給你一個完整的程式 段去實驗一下:
#include <stdio.h>
int abc(long double a[])
{
unsigned int fR=sizeof(a);
return fR;
}
int main(void)
{
long double p[2]={0.0};
printf("%d",abc(p));
return 0;
}
各位也許認為上面那道題目太簡單了。那麼我們這次就可以來一個…………………………………
…更簡單的了。
struct M
{
char a;
int b;
long c;
}
如果我們現在來sizeof(M)那麼得到的結果是什麼呢?也許你這次會說是9,或15。(隻是也許。
我知道,高手有很多。)但是正确的答案是16。下面我将為讀者來解釋下這個答案的名字:這是C99的一
個标準,它的名字叫記憶體對齊。CPU在通路記憶體對齊的變量的時候,速度會加快。可以說,這是标準跟我
們開的一個玩笑。
當然,為了以後我們能夠準确計算出結構體所占的空間,我将為電腦 前的您來講解如何計算這種
“特殊的結果”。
您有兩種方法來了解“記憶體對齊”,但在文章的最後,我将會講解這兩種方法之間的微妙關系。
1.在大多數編譯器中,預設的記憶體對齊大小為8。當資料的大小大于8時,也會被當做8處理。當
然,你也可以更改。我們來依次了解:
//我們先要知道,我們可以以8個位元組為一個大機關,當然,這個8是可以更改的。
char a; //那麼char的位元組為1,先進入到了這個“大機關”中
int b;//int為4位元組,大機關中還餘下了7個小機關,也可以擠進去。
long c;//long也為4位元組,可是此時大機關中還隻剩下了3個機關,因為有5個機關被char和int
使用了。是以不能再擠進去了,于是另外開辟了一個大機關,把4個小機關放了進入。至此,總共用了2個
大機關,而一個大機關是8個小機關,也就是8個位元組,是以最終的結果是8*2=16位元組。
2.嗯,我們還有另一種方法來了解,這種了解起來要難得多。
我們可以把結構體内的成員當作一個個的乘客,人人都想到第一個位置,也就是在記憶體中的首
位置。但是這個位置隻有第一個成員才可以拿到。我們可以把他所在的位置與頭位置的差叫做“偏移量”
。當偏移量是本身所占位元組的倍數的時候,就不用填補。而不是的時候,就要填補到是自身的倍數,并且
自身要占8個位元組。
char a;//此時偏移量為0,是1的倍數。此時所占大小為1
int b;//此時偏移量為1,因為前面的char所占了一個位元組。1不是4的倍數,是以要加3,以變
成4,成為4的倍數,并且b本身也占了8個位元組(可以當成運氣不好的懲罰吧,呵呵),那麼此時又占了
3+8個位元組。總占11個位元組。
long c;//此時偏移量為1+11=12。12是4的倍數,是以無需另加機關。此時又占了4個位元組。總
占4+11+1個位元組,也就是16個位元組。
說了這麼多。其實兩種方法也就是一個方法。當判斷偏移量是否為自身大小的倍數的時候,其
實就是在判斷“是否還能夠擠進一個大機關”中。當全部判斷完後。空的大小(也就是對齊的大小)是一
樣的。
摘自:http://www.hack4.com/article/hack4-21692.html