sizeof 筆記(轉自http://student.csdn.net/space.php?uid=43658&do=blog&id=8677)

大家是否發現sizeof好多什麼很煩人。。老是弄錯的時候。實在沒辦法了。。對它做下總結吧。。希望以後少出錯。。

1 sizeof 是什麼?

   sizeof()不是函數,不是宏。它是一個關鍵字。一個運算符。

2 sizeof用來幹什麼?

  sizeof()他可以獲得一中數據類型(內置類型或自定義類型)或一個變量所佔字節的大小。結果爲一個十進制數。

3 sizeof()和strlen()的區別。

  現在我們知道sizeof是一個運算符了。那strlen是什麼呢?我們去MSDN上看下:

Code:
  1. size_t strlen( const char *string );   
  2. size_t wcslen( const wchar_t *string );  

這是MSDN的結果。也就是說strlen()是一個函數,返回類型爲size_t。參數爲const char *.好。我們明白了,下面我們看幾個例子來區分一下吧:

第一個例子:

Code:
  1. char * p = "123456";   
  2. cout << sizeof(p) << endl;// 結果爲4   
  3. cout << sizeof(*p) << endl;//結果爲1   
  4. cout << strlen(p) << endl;//結果爲6   

首相記住一句話,所有指針(包括void*)所佔的大小均爲4個字節。故第一個結果爲4。這點到令我想起了類。我們知道在一個類未定義完成之前我們是無法用它來定義對象的。然而我們可以用它來定義指針成員。爲什麼呢?因爲當我們用一個類型來定義對象時。我們在編譯時必須知道這個類型的大下,該爲此對象非配多大的空間。而此時我們的類並沒有定義完整,編譯器是無法得知類的大小的。故也就無法爲該類的對象分配空間。故就乾脆禁止定義類對象。而指針就不同了。因爲任何類型的指針大小均爲4.故編譯器一看到指針直接分配4個字節就對了。。呵呵。。

程序的第二行結果爲1,因爲指針p中存放的是字符串的首地址。即字符串第一個字符的地址。*p也就是字符串第一個字符。類型爲char故結果爲1.

第三行strlen是用來求字符串的長度,不含結束符"/0";故結果爲6

第二個例子:

Code:
  1. char a[100] = "123456";   
  2. cout << sizeof(a) << endl; //結果爲100   
  3. cout << strlen(a) << endl; // 結果爲6  

第一行:結果爲100.是因爲在我們定義字符數組時,下標標出了100,此時編譯器就會爲我們分配100*sizeof(char)的內存空間。

第二行:結果類似第一個例子,是對該數組求長度。

第三個例子:

Code:
  1. char a[] = "123456";   
  2. cout << sizeof(a) << endl; //結果爲7   
  3. cout << strlen(a) << endl; //j結果爲6   

第一行:結果爲7,是因爲編譯器在爲數組分配空間時,看到數組a中沒有標下標,故就根據後面字符串的長度來爲該數組分配空間。而後面字符串的長度爲7(包括結束符"/0"),故結果爲7;

第四個例子:

Code:
  1. int a[100] = {1,2,3};   
  2. cout << sizeof(a) << endl; //結果爲400   
  3. cout << strlen(a) << endl; //錯誤  

第一行:由於a是int行數組,故結果爲100*sizeof(int).

第二行之所以錯誤是因爲我們的strlen是個函數,它的參數是const char*。

4 sizeof的怪用

sizeof可以做數組的下標使用,作用類似於我們C++中的const。類似C中的define。呵呵。不知道吧。。我們看個例子:

Code:
  1. int a[sizeof(int)] = {1,3,4,5};  

編譯下,成功了。。呵呵。。若是我們改成下面這樣:

Code:
  1. int a[sizeof(int)] = {1,3,4,5,6,7};  

錯誤:too many initializers

爲什麼會成功呢?因爲sizeof在編譯的時候就被計算過了。。呵呵

5 牽涉到特殊字符時候的sizeof計算

 這裏的特殊字符指那些類似 '/n','/t','//','/0'的東西。記住遇到這些東西的時候,把它當做1計算就對了。。如:

Code:
  1. char a[] = "b/n";   
  2. cout << sizeof(a) << endl; //結果爲3  

6 牽涉到函數的sizeof

這裏有兩種含義,一種是對函數求sizeof。

這就怪了,我剛纔還說sizeof僅對數據類型或變量求值的。呵呵。。其實這並沒有違揹我剛剛纔的話。我們看下面例子:

Code:
  1. double f();   
  2. cout << sizeof(f()) << endl; //結果爲8  

我們定義了一個函數f(),然後對它進行sizeof.還得出了結果。其實這裏sizeof是對函數的返回類型進行了求值。因爲f()的返回類型爲double類型。故結果爲8.

第二種函數,對函數裏面的變量求值。

啊?函數裏面的變量和其他的變量不一樣?呵呵。一樣的。不過有些變量傳進來之後會改變身份的。。我們看下面例子:

Code:
  1. #include <iostream>   
  2. using namespace std;   
  3. void f(char a[]);   
  4. int main()   
  5. {   
  6.     char a[] = "123456";   
  7.     f(a);   
  8.     return 0;   
  9. }   
  10. void f(char a[])   
  11. {   
  12.     cout << sizeof(a) << endl; //結果爲4   
  13.     return 0;   
  14. }  

結果爲什麼成4了呢。不該是7嗎?這是因爲a傳進函數之後就退化成一個指針了。

7 牽涉到結構體的sizeof

這裏就要考慮的東西多了,牽涉到結構體對齊,數據對齊問題了。很是煩人。

但是我們可以不然編譯器進行結構體對齊:

我們使用這個#pragma pack(n)。n爲指定的對齊數。當n==1時。這時候結構體便不再老老實實的輸出實際的字節長度了。如:

Code:
  1. #include <iostream>   
  2. using namespace std;   
  3. #pragma pack(1)   
  4. struct stu   
  5. {   
  6.     char c;   
  7.     int a;   
  8. };   
  9. int main()   
  10. {   
  11.     cout << sizeof(stu) << endl;   
  12.     return 0;   
  13. }  

輸出結果爲5.當我們去掉:#pragma pack(1)後,結果爲8。

如果我們改下n的值爲2.此時運行結果爲6.

n的值爲3 時。哇!!編譯器給出警告了。。說n的值只能是 1, 2 ,4, 8 ,16.

n的值爲4時,結果爲8.

n的值爲8時,結果爲8

n的值爲16時。結果爲8.

由此我們可以總結出一下幾點:

①: 編譯器是根據 #pragma pack(n) 中n的值和當前對象進行比較進行字節對齊的。

②:當 :#pragma pack(n) 中n的值大於等於結構體中最大長度變量時。n值將不再起作用。此時編譯器將根據最大長度值和當前變量進行字節對齊。

 ③ 當我們的n值爲1時。將不進行任何的補齊。輸出實際的變量大小之和。

我們用的win32操作系統默認的應該是8字節對齊的即n== 8;所以我們平時考慮字節對齊時只需跟句最大變量進行對齊即可:

這裏的規則大家可以參考資料:

http://space.itpub.net/14805538/viewspace-483697

http://www.diybl.com/course/3_program/c++/cppjs/20090403/163712.html

這些都是google出來的。大家若是想了解更對的東西不妨也google一下吧。

另外除了結構體對齊的原因需要考慮外,千萬別忘了有些變量是不再sizeof的計算範圍之內的。如:

靜態變量。enum。union。

Code:
  1. #include <iostream>   
  2. using namespace std;   
  3. #pragma pack(16)   
  4. struct stu   
  5. {   
  6.  char c;   
  7.  static long double a;   
  8.  union t   
  9.  {   
  10.     int a;   
  11.     int b;   
  12.  };   
  13.  enum weekday{Monday};   
  14. };   
  15. int main()   
  16. {   
  17.     cout << sizeof(stu) << endl; //結果爲1   
  18.     return 0;   
  19. }  

8 牽涉到類的sizeof

這個就更麻煩了。。不但要考慮到結構體對齊問題,還要考慮虛函數,虛繼承等等。在類裏除了結構體中提到的那些不佔空間外,普通函數也是不佔空間的。至於這裏的sizeof就不再總結了。太多了。大家可以google下。呵呵。。

9 其他的sizeof

 有關標準庫的sizeof你試過嗎?如是沒有的話,不妨可以去了解下哦。。呵呵。。

Code:
  1. cout << sizeof(string) << endl;   
  2. cout << sizeof(vector<int>) << endl;   
  3. cout << sizeof(vector<string>) << endl;   
  4. cout << sizeof(list<int>) << endl;   
  5. cout << sizeof(deque<int>) << endl;      
  6. string str[] = {"hello","world","nihao"};   
  7. cout << sizeof(str)/sizeof(string) << endl;   
  8. string *pstr = new string[2];   
  9. cout << sizeof(pstr)<< endl;  

若是有時間的話,上面的這些還是運行下看下結果唄。。呵呵。。瞭解一下。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章