1. 程式人生 > >C/C++中sizeof()的用法——32位和64位下的sizeof()

C/C++中sizeof()的用法——32位和64位下的sizeof()

機器平臺:X86_64 處理器

作業系統:Red Hat 4.1.2-14

編譯器: gcc version 4.1.2 20070626

Size of char is:                                   1

Size of unsigned char is:                     1

Size of signed char is:                  1

Size of int is:                                    4

Size of short is:                                2

Size of long is:                                  8

Size of long int is:                             8

Size of signed int is:                           4

Size of unsigned int is:                       4

Size of unsigned long int is:                8

Size of long long int is:                       8

Size of unsigned long long is:              8

Size of float is:                    4

Size of double is:                 8

Size of long double is:          16

Size of (void *) is:           8

Size of (char *) is:           8

Size of (int *) is:             8

Size of (long *) is:           8

Size of (long long *) is:   8

Size of (float *) is:          8

Size of (double *) is:              8

 所有指標都是佔8位元組

——————————————————————————

機器平臺: X86_32 處理器

作業系統:  Windows XP SP2

編譯器:    VS2005自帶的C++編譯器

Size of char is:                            1

Size of unsigned char is:              1

Size of signed char is:           1

Size of int is:                       4

Size of short is:                    2

Size of long is:                     4

Size of long int is:                4

Size of signed int is:             4

Size of unsigned int is:          4

Size of unsigned long int is:         4

Size of long long int is:                8

Size of unsigned long long is:       8

Size of float is:                    4

Size of double is:                 8

Size of long double is:          8

Size of (void *) is:          4    

Size of (char *) is:          4

Size of (int *) is:             4

Size of (long *) is:          4

Size of (long long *) is:   4

Size of (float *) is:          4

Size of (double *) is:       4

所有指標都是佔4位元組

sizeof()功能:計算資料空間的位元組數
1.與strlen()比較
      strlen()計算字元陣列的字元數,以"\0"為結束判斷,不計算為'\0'的陣列元素。
      而sizeof計算資料(包括陣列、變數、型別、結構體等)所佔記憶體空間,用位元組數表示。
2.指標與靜態陣列的sizeof操作
      指標均可看為變數型別的一種。所有指標變數的sizeof 操作結果均為4。
注意:int *p; sizeof(p)=4;
                  但sizeof(*p)相當於sizeof(int);      
      對於靜態陣列,sizeof可直接計算陣列大小;
      例:int a[10];char b[]="hello";
              sizeof(a)等於4*10=40;
              sizeof(b)等於6;
 注意:陣列做型參時,陣列名稱當作指標使用!!
               void  fun(char p[])
               {sizeof(p)等於4}    
經典問題: 
      double* (*a)[3][6]; 
      cout<<sizeof(a)<<endl; // 4 a為指標
      cout<<sizeof(*a)<<endl; // 72 *a為一個有3*6個指標元素的陣列
      cout<<sizeof(**a)<<endl; // 24 **a為陣列一維的6個指標
      cout<<sizeof(***a)<<endl; // 4 ***a為一維的第一個指標
cout<<sizeof(****a)<<endl; // 8 ****a為一個double變數
問題解析:a是一個很奇怪的定義,他表示一個指向double*[3][6]型別陣列的指標。既然是指標,所以sizeof(a)就是4 既然a是執行double*[3][6]型別的指標,*a就表示一個double*[3][6]的多維陣列型別,因此sizeof(*a)=3*6*sizeof(double*)=72。同樣的,**a表示一個double*[6]型別的陣列,所以sizeof(**a)=6*sizeof  (double*)=24***a就表示其中的一個元素,也就是double*了,所以sizeof(***a)=4。至於****a,就是一個double了,所以sizeof(****a)=sizeof(double)=8 
3.格式的寫法
   sizeof操作符,對變數或物件可以不加括號,但若是型別,須加括號。
4
.使用sizeof時string的注意事項
   string s="hello";
   sizeof(s)等於string類的大小,sizeof(s.c_str())得到的是與字串長度。
5.union 與struct的空間計算
   總體上遵循兩個原則:
   (1)整體空間是 
佔用空間最大的成員(的型別)所佔位元組數的整倍數
   (2)資料對齊原則----記憶體按結構成員的先後順序排列,當排到該成員變數時,其前面已擺放的空間大小必須是該成員型別大小的整倍數,如果不夠則補齊,以此向後類推。。。。。
   注意:陣列按照單個變數一個一個的擺放,而不是看成整體。如果成員中有自定義的類、結構體,也要注意陣列問題。
例:[引用其他帖子的內容]
因為對齊問題使結構體的sizeof變得比較複雜,看下面的例子:(預設對齊方式下)

struct s1
{
char a;
double b;
int c;
char d; 
};

struct s2
{
char a;
char b;
int c;
double d;
};

cout<<sizeof(s1)<<endl; // 24
cout<<sizeof(s2)<<endl; // 16

同樣是兩個char型別,一個int型別,一個double型別,但是因為對齊問題,導致他們的大小不同。計算結構體大小可以採用元素擺放法,我舉例子說明一下:首先,CPU判斷結構體的對界,根據上一節的結論,s1s2的對界都取最大的元素型別,也就是double型別的對界8。然後開始擺放每個元素。對於s1,首先把a放到8的對界,假定是0,此時下一個空閒的地址是1,但是下一個元素ddouble型別,要放到8的對界上,離1最接近的地址是8了,所以d被放在了8,此時下一個空閒地址變成了16,下一個元素c的對界是416可以滿足,所以c放在了16,此時下一個空閒地址變成了20,下一個元素d需要對界1,也正好落在對界上,所以d放在了20,結構體在地址21處結束。由於s1的大小需要是8的倍數,所以21-23的空間被保留,s1的大小變成了24對於s2,首先把a放到8的對界,假定是0,此時下一個空閒地址是1,下一個元素的對界也是1,所以b擺放在1,下一個空閒地址變成了2;下一個元素c的對界是4,所以取離2最近的地址4擺放c,下一個空閒地址變成了8,下一個元素d的對界是8,所以d擺放在8,所有元素擺放完畢,結構體在15處結束,佔用總空間為16,正好是8的倍數。這裡有個陷阱,對於結構體中的結構體成員,不要認為它的對齊方式就是他的大小,看下面的例子:
struct s1
{
char a[8];
};

struct s2
{
double d;
};

struct s3
{
s1 s;
char a;
};

struct s4
{
s2 s;
char a; 
};
cout<<sizeof(s1)<<endl; // 8
cout<<sizeof(s2)<<endl; // 8
cout<<sizeof(s3)<<endl; // 9
cout<<sizeof(s4)<<endl; // 16;
  s1
s2大小雖然都是8,但是s1的對齊方式是1s28double),所以在s3s4中才有這樣的差異。所以,在自己定義結構體的時候,如果空間緊張的話,最好考慮對齊因素來排列結構體裡的元素。
補充:不要讓double干擾你的位域 
  在結構體和類中,可以使用位域來規定某個成員所能佔用的空間,所以使用位域能在一定程度上節省結構體佔用的空間。不過考慮下面的程式碼: 

struct s1 

 int i: 8; 
 int j: 4; 
 double b; 
 int a:3; 
}; 

struct s2 

 int i; 
 int j; 
 double b; 
 int a; 
}; 

struct s3 

 int i; 
 int j; 
 int a; 
 double b; 
}; 

struct s4 

 int i: 8; 
 int j: 4; 
 int a:3; 
 double b; 
}; 

cout<<sizeof(s1)<<endl; // 24 
cout<<sizeof(s2)<<endl; // 24 
cout<<sizeof(s3)<<endl; // 24 
cout<<sizeof(s4)<<endl; // 16 
  可以看到,有double存在會干涉到位域(sizeof的演算法參考上一節),所以使用位域的的時候,最好把float型別和double型別放在程式的開始或者最後。