日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
C/C++基礎(chǔ)之sizeof使用

在 C/C++ 中,sizeof() 是一個(gè)判斷數(shù)據(jù)類型或者表達(dá)式長(zhǎng)度的運(yùn)算符。

1、sizeof 定義sizeof 是 C/C++ 中的一個(gè)操作符(operator),返回一個(gè)對(duì)象或者類型所占的內(nèi)存字節(jié)數(shù)。

The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type(including aggregate types). This keyword returns a value of type size_t.

——來(lái)自MSDN

其返回值類型為 size_t ,在頭文件 stddef.h 中定義為: typedef unsigned int size_t;

從sizeof 的定義可以看出:sizeof 不是一個(gè)函數(shù),因?yàn)楹瘮?shù)調(diào)用必須有一對(duì)括號(hào)。

 
 
 
 
  1. #include  
  2.  
  3. int main(void) 
  4.    int num = 97; 
  5.  
  6.    printf("sizeof(num = 0)的值:%d\n",sizeof(num = 0));    
  7.    printf("num 的值:%d\n",num);    
  8.    return 0; 

 

 

運(yùn)行結(jié)果為4,97;并不是4,0

說(shuō)明:sizeof 不是標(biāo)準(zhǔn)意義上的一元操作符,不支持鏈?zhǔn)奖磉_(dá)式,sizeof 作用域范圍內(nèi)的語(yǔ)句不會(huì)編譯成機(jī)器碼,如 sizeof(num++) 中的 ++ 不執(zhí)行。sizeof 也不是函數(shù), sizeof 更像一個(gè)特殊的宏,在編譯階段求值。

2、sizeof 用法sizeof 有兩種語(yǔ)法形式,如下:

 
 
 
 
  1. sizeof(type_name);    //sizeof(類型); 
  2. sizeof (object);      //或sizeof object 都屬于 sizeof對(duì)象; 

所以:

 
 
 
 
  1. int i; 
  2. sizeof(i);    //合理 
  3. sizeof i;     //合理 
  4. sizeof(int);  //合理 
  5. sizeof int;   //不合理 
  • 對(duì)類型使用 sizeof 時(shí),sizeof type_name 是非法的,必須寫(xiě)為 sizeof(type_name);
  • 無(wú)論是對(duì)對(duì)象還是類型取值,sizeof () 這種形式都是對(duì)的;

1)基本數(shù)據(jù)類型的 sizeof

這里的基本數(shù)據(jù)類型是指short、int、long、float、double這樣的簡(jiǎn)單內(nèi)置數(shù)據(jù)類型。

由于它們的內(nèi)存大小是和系統(tǒng)相關(guān)的,所以在不同的系統(tǒng)下取值可能不同。

 
 
 
 
  1. #include  
  2. using namespace std; 
  3.   
  4. int main() 
  5.    cout << "Size of char : " << sizeof(char) << endl; 
  6.    cout << "Size of int : " << sizeof(int) << endl; 
  7.    cout << "Size of short int : " << sizeof(short int) << endl; 
  8.    cout << "Size of long int : " << sizeof(long int) << endl; 
  9.    cout << "Size of float : " << sizeof(float) << endl; 
  10.    cout << "Size of double : " << sizeof(double) << endl; 
  11.    cout << "Size of wchar_t : " << sizeof(wchar_t) << endl; 
  12.    return 0; 

在 32 位系統(tǒng)下內(nèi)置數(shù)據(jù)類型與其 sizeof 運(yùn)算結(jié)果如下:

 
 
 
 
  1. Size of char : 1 
  2. Size of int : 4 
  3. Size of short int : 2 
  4. Size of long int : 4 
  5. Size of float : 4 
  6. Size of double : 8 
  7. Size of wchar_t : 4 
  • unsigned 不影響內(nèi)置類型 sizeof 的取值

2) 指針類型的 sizeof

指針主要用于存儲(chǔ)地址,前幾天文章C語(yǔ)言指針詳解提到過(guò),指針變量的位寬等于機(jī)器字長(zhǎng),機(jī)器字長(zhǎng)由 CPU 寄存器位數(shù)決定。在 32 位系統(tǒng)中,一個(gè)指針變量的返回值為 4 字節(jié), 64 位系統(tǒng)中指針變量的 sizeof 結(jié)果為 8 字節(jié)。

 
 
 
 
  1. char *p =”hello”;  
  2. sizeof( p );       // 結(jié)果為4  
  3. sizeof(*p);        // 結(jié)果為1  
  4. int *pi;  
  5. sizeof( pi );      //結(jié)果為4  
  6. sizeof(*pi);       //結(jié)果為4  
  7. char **pp = &p;  
  8. sizeof( pp );      // 結(jié)果為4  
  9. sizeof( *pp );     // 結(jié)果為4  
  • 指針變量的 sizeof 值與指針?biāo)傅膶?duì)象類型沒(méi)有任何關(guān)系,與指針申請(qǐng)多少空間沒(méi)有關(guān)系,所有的指針變量所占內(nèi)存大小均相等。
  • 如果使用 32 位編譯器編譯得到程序是 32 位,那么在 64bits 系統(tǒng)下,指針變量大小仍然是 4 個(gè)字節(jié)。

3) 函數(shù)類型的 sizeof

函數(shù)類型以其返回類型作為自身類型,進(jìn)行 sizeof 取值。

 
 
 
 
  1. void fun1() 
  2. int fun2() 
  3.    return 0; 
  4. double fun3() 
  5.    return 0.0; 
  6. cout << sizeof(fun1()) << endl;  //錯(cuò)誤!無(wú)法對(duì)void類型使用sizeof 
  7. cout << sizeof(fun2()) << endl;  //fun2()返回值類型為int,輸出4 
  8. cout << sizeof(fun3()) << endl;  //fun3()返回值類型為double,輸出8 

注意:不能對(duì)返回 void 函數(shù)和函數(shù)指針進(jìn)行 sizeof 取值。

4) 數(shù)組類型的 sizeof

當(dāng) sizeof 作用于數(shù)組時(shí),求取的是數(shù)組所有元素所占用的大小。

 
 
 
 
  1. int A[3][5]; 
  2.     char c[]="abcdef"; 
  3.     double*(*d)[3][6]; 
  4.  
  5.     cout<
  6.     cout<
  7.     cout<
  8.     cout<
  9.     cout<
  10.     cout<
  11.     cout<
  12.     cout<
  13.     cout<

A 的數(shù)據(jù)類型是 int[3][5] ,A[4] 的數(shù)據(jù)類型是 int[5],A[0][0]數(shù)據(jù)類型是 int 。所以:

 
 
 
 
  1. sizeof(A)==sizeof(int[3][5])==3*5*sizeof(int)==60 
  2. sizeof(A[4])==sizeof(int[5])=5*sizeof(int)==20 
  3. sizeof(A[0][0])==sizeof(int)==4 

如果字符數(shù)組表示字符串,數(shù)組末自動(dòng)插入 '\0',所以 c 的數(shù)據(jù)類型是 char[7] ,所以 sizeof(c)=sizeof(char[7])==7。

d 是一個(gè)很奇怪的定義,他表示一個(gè)指向 double*[3][6] 類型數(shù)組的指針。既然是指針,所以 sizeof(d) 就是4。

既然 d 是執(zhí)行 double*[3][6] 類型的指針, *d 就表示一個(gè) double*[3][6] 的多維數(shù)組類型,因此 sizeof(*a)=3*6*sizeof(double*)=72 。

**d 表示一個(gè) double*[6] 類型的數(shù)組,所以 sizeof(**d)=6*sizeof (double*)=24。

***d 表示其中的一個(gè)元素,也就是 double* ,所以 sizeof(***d)=4 。

****d 是一個(gè) double ,所以 sizeof(****d)=sizeof(double)=8。

當(dāng)數(shù)組作為函數(shù)形參時(shí),下面輸出結(jié)果應(yīng)該是多少呢?

 
 
 
 
  1. int GetStrLength(char str[]) 
  2.    return sizeof(str); 
  3.  
  4. int main() 
  5.    char szStr[] = "abcdef"; 
  6.    cout<< GetStrLength() << endl; 
  7.    return 0; 

輸出不是 7 ,這里函數(shù)參數(shù) str[] 已不再是數(shù)組類型,而是蛻變成指針,我們調(diào)用函數(shù) GetStrLength() 時(shí),程序會(huì)在棧上分配一個(gè)大小為 7 的數(shù)組嗎?不會(huì)!數(shù)組是“傳址”的,調(diào)用者只需將實(shí)參的地址傳遞過(guò)去,所以 str 自然為指針類型 (char*) ,輸出值為:4 。

  • 數(shù)組的大小是各維數(shù)的乘積*數(shù)組元素的大小。
  • 向函數(shù)形參傳遞數(shù)組,數(shù)組將會(huì)退化為指針,失去原來(lái)數(shù)組的特性。

5) 結(jié)構(gòu)體類型的 sizeof

對(duì)于 struct 數(shù)據(jù)結(jié)構(gòu)由 CPU 的對(duì)齊問(wèn)題導(dǎo)致 struct 的大小變得比較復(fù)雜。具體可以查看以前的文章一文輕松理解內(nèi)存對(duì)齊。

理論上,int 占 4byte , char 占一個(gè) byte ,那么將它們放到一個(gè)結(jié)構(gòu)體中應(yīng)該占 4+1=5byte ;但是實(shí)際上,通過(guò)運(yùn)行程序得到的結(jié)果是 8byte 。

 
 
 
 
  1. #include 
  2.  
  3. struct{ 
  4.     int x; 
  5.     char y; 
  6. }Test; 
  7.  
  8. int main() 
  9.     printf("%d\n",sizeof(Test)); // 輸出8不是5 
  10.     return 0; 

結(jié)構(gòu)體的大小跟結(jié)構(gòu)體成員對(duì)齊有密切關(guān)系,而并非簡(jiǎn)單地等于各個(gè)成員的大小之和!比如對(duì)如下結(jié)構(gòu)體兩個(gè)結(jié)構(gòu)體 A、B 使用 sizeof 的結(jié)果分別是:16,24??梢钥闯?sizeof(B) 并不等于 sizeof(int)+sizeof(double)+sizeof(int)=16 。

 
 
 
 
  1. struct A 
  2.   int num1; 
  3.   int num2; 
  4.   double num3; 
  5. }; 
  6. struct B 
  7.   int num1; 
  8.   double num3; 
  9.   int num2; 
  10. }; 

結(jié)構(gòu)體A和B中包含的成員都一樣,只不過(guò)順序不同而已,為什么其大小不一樣呢?要解釋這個(gè)問(wèn)題,就要了解結(jié)構(gòu)體成員對(duì)齊的規(guī)則。

  • 結(jié)構(gòu)體的大小等于結(jié)構(gòu)體內(nèi)最大成員大小的整數(shù)倍
  • 結(jié)構(gòu)體內(nèi)的成員的首地址相對(duì)于結(jié)構(gòu)體首地址的偏移量是其類型大小的整數(shù)倍,比如說(shuō) double 型成員相對(duì)于結(jié)構(gòu)體的首地址的地址偏移量應(yīng)該是 8 的倍數(shù)。
  • 為了滿足規(guī)則 1 和 2 編譯器會(huì)在結(jié)構(gòu)體成員之后進(jìn)行字節(jié)填充!

從三個(gè)規(guī)則我們來(lái)看看為什么 sizeof(B) 等于 24 :首先假設(shè)結(jié)構(gòu)體的首地址為0,第一個(gè)成員 num1 的首地址是 0 (滿足規(guī)則2),它的類型是 int ,因此它占用地址空間 0——3 。第二個(gè)成員 num3 是 double 類型,它占用 8 個(gè)字節(jié),由于之前的 num1 只占用了 4 個(gè)字節(jié),為了滿足規(guī)則 2 ,需要使用規(guī)則 3 在 num1 后面填充 4 個(gè)字節(jié)(4——7),使得 num3 的起始地址偏移量為 8 ,因此 num3 占用的地址空間是:8——15。第三個(gè)成員 num2 是 int 型,其大小為 4 ,由于 num1 和num3 一共占用了 16 個(gè)字節(jié),此時(shí)無(wú)須任何填充就能滿足規(guī)則 2。因此 num2 占用的地址空間是 16——19 。那么是不是結(jié)構(gòu)體的總大小就是 0——19 共 20 個(gè)字節(jié)呢?請(qǐng)注意,別忘了規(guī)則1!由于結(jié)構(gòu)體內(nèi)最大成員是 double 占用 8 個(gè)字節(jié),因此最后還需要在 num2 后面填充 4 個(gè)字節(jié),使得結(jié)構(gòu)體總體大小為 24 。

 
 
 
 
  1. struct S{ };  
  2. sizeof(S); // 結(jié)果為1 

對(duì)于一個(gè)空 struct 結(jié)構(gòu)體取 sizeof 運(yùn)算,運(yùn)算結(jié)果為 1 并非 0 。因?yàn)榫幾g器為保證此空 struct 存在,專門(mén)分配一個(gè)字節(jié)。

如果存在結(jié)構(gòu)體嵌套,無(wú)論內(nèi)層還是外層均需要采用內(nèi)存對(duì)齊。

6) 類的 sizeof

1.不含繼承和 static 成員變量的類。

在這種情況下,只需要考慮對(duì)齊方式即可。

 
 
 
 
  1. class A  
  2. {  
  3.   public:  
  4.   int b;  
  5.   float c;  
  6.   char d;  
  7. }; 
  8. class B 
  9. {  
  10. }; 
  11.  
  12. int main(void)  
  13. {  
  14.   cout << “sizeof(A) is ” << sizeof(A) << endl;  
  15.   //輸出結(jié)果為12 
  16.   cout << “sizeof(B) is ” << sizeof(B) << endl;  
  17.   //輸出結(jié)果為1 
  18.   return 0 ;  
  • 空的 class 同樣也占用 1 個(gè)字節(jié)。
  • 計(jì)算類對(duì)象的大小時(shí),類成員函數(shù)不占用對(duì)象空間,只需要考慮類中數(shù)據(jù)成員的大小。

2.類中存在靜態(tài)成員變量

 
 
 
 
  1. class A  
  2. {  
  3.   public:  
  4.   static int a;  
  5.   int b;  
  6.   float c;  
  7.   char d;  
  8. }; 
  9.  
  10. int main()  
  11. {  
  12.   A object;  
  13.   cout << “sizeof(object) is ” << sizeof(object) << endl;  
  14.   //輸出結(jié)果為12 
  15.   return 0 ;  

因?yàn)樵诔绦蚓幾g期間,就已經(jīng)為 static 變量在靜態(tài)存儲(chǔ)區(qū)域分配了內(nèi)存空間,并且這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。而每次聲明了類 A 的一個(gè)對(duì)象的時(shí)候,為該對(duì)象在堆上,根據(jù)對(duì)象的大小分配內(nèi)存。

3.類中包含成員函數(shù)

 
 
 
 
  1. class A  
  2. {  
  3.   public:  
  4.   static int a;  
  5.   int b;  
  6.   float c;  
  7.   char d;  
  8.   int add(int x,int y)  
  9.   {  
  10.     return x+y;  
  11.   }  
  12. }; 
  13.  
  14. int main()  
  15. {  
  16.   A object;  
  17.   cout << “sizeof(object) is ” << sizeof(object) << endl;  
  18.   b = object.add(3,4);  
  19.   cout << “sizeof(object) is ” << sizeof(object) << endl;  
  20.   //輸出結(jié)果為12 
  21.   return 0 ;  

因?yàn)橹挥蟹庆o態(tài)類成員變量在新生成一個(gè)object的時(shí)候才需要自己的副本。所以每個(gè)非靜態(tài)成員變量在生成新object需要內(nèi)存,而function是不需要的。

3、sizeof 與 strlen 區(qū)別

  • sizeof 是一個(gè)操作符,strlen 是庫(kù)函數(shù)。
  • sizeof 的參數(shù)可以是數(shù)據(jù)的類型,也可以是變量,而 strlen 只能以結(jié)尾
  • 編譯器在編譯時(shí)就計(jì)算出了 sizeof 的結(jié)果,而 strlen 函數(shù)必須在運(yùn)行時(shí)才能計(jì)算出來(lái)。并且 sizeof 計(jì)算的是數(shù)據(jù)類型占內(nèi)存的大小,而 strlen 計(jì)算的是字符串實(shí)際的長(zhǎng)度。
  • 數(shù)組做 sizeof 的參數(shù)不退化,傳遞給 strlen 就退化為指針了。如:

 

 
 
 
 
  1. int ss[20]="0123456789"; 
  2.  sizeof(ss)=80, //ss表示在內(nèi)存中的大小,20*4。 
  3.  strlen(ss)    //錯(cuò)誤,strlen的參數(shù)只能是char*,且必須是以“\0”結(jié)尾的。 
  4.  char *ss="0123456789"; 
  5.  sizeof(ss)=4,  //ss是指向字符串常量的字符指針。 
  6.  sizeof(*ss)=1, // *ss是第一個(gè)字符。 

參考資料

  • https://www.cnblogs.com/Western-Trail/p/10326180.html
  • 《C/C++實(shí)踐進(jìn)階之道》

分享標(biāo)題:C/C++基礎(chǔ)之sizeof使用
標(biāo)題鏈接:http://m.5511xx.com/article/codjehg.html