1. 定義ios
sizeof是一個操做符(operator)。數組
其做用是返回一個對象或類型所佔的內存字節數。函數
2. 語法spa
sizeof有三種語法形式:指針
1) sizeof (object); //sizeof (對象)code
2) sizeof object; //sizeof 對象對象
3) sizeof (type_name); //sizeof (類型)blog
對象能夠是各類類型的變量,以及表達式(通常sizeof不會對錶達式進行計算)。內存
sizeof對對象求內存大小,最終都是轉換爲對對象的數據類型進行求值。字符串
sizeof (表達式); //值爲表達式的最終結果的數據類型的大小
舉例:
int i; sizeof(int); //值爲4 sizeof(i); //值爲4,等價於sizeof(int) sizeof i; //值爲4 sizeof(2); //值爲4,等價於sizeof(int),由於2的類型爲int sizeof(2 + 3.14); //值爲8,等價於sizeof(double),由於此表達式的結果的類型爲double char ary[sizeof(int) * 10]; //OK,編譯無誤
1. 基本數據類型的sizeof
這裏的基本數據類型是指short、int、long、float、double這樣的簡單內置數據類型。
因爲它們的內存大小是和系統相關的,因此在不一樣的系統下取值可能不一樣。
2. 結構體的sizeof
結構體的sizeof涉及到字節對齊問題。
爲何須要字節對齊?計算機組成原理教導咱們這樣有助於加快計算機的取數速度,不然就得多花指令週期了。爲此,編譯器默認會對結構體進行處理(實際上其它地方的數據變量也是如此),讓寬度爲2的基本數據類型(short等)都位於能被2整除的地址上,讓寬度爲4的基本數據類型(int等)都位於能被4整除的地址上,依次類推。這樣,兩個數中間就可能須要加入填充字節,因此整個結構體的sizeof值就增加了。
字節對齊的細節和編譯器的實現相關,但通常而言,知足三個準則:
1) 結構體變量的首地址可以被其最寬基本類型成員的大小所整除。
2) 結構體的每一個成員相對於結構體首地址的偏移量(offset)都是成員大小的整數倍,若有須要,編譯器會在成員之間加上填充字節(internal adding)。
3) 結構體的總大小爲結構體最寬基本類型成員大小的整數倍,若有須要,編譯器會在最末一個成員後加上填充字節(trailing padding)。
注意:空結構體(不含數據成員)的sizeof值爲1。試想一個「不佔空間「的變量如何被取地址、兩個不一樣的「空結構體」變量又如何得以區分呢,因而,「空結構體」變量也得被存儲,這樣編譯器也就只能爲其分配一個字節的空間用於佔位了。
例子:
struct S1 { char a; int b; }; sizeof(S1); //值爲8,字節對齊,在char以後會填充3個字節。 struct S2 { int b; char a; }; sizeof(S2); //值爲8,字節對齊,在char以後會填充3個字節。 struct S3 { }; sizeof(S3); //值爲1,空結構體也佔內存
3. 聯合體的sizeof
結構體在內存組織上市順序式的,聯合體則是重疊式,各成員共享一段內存;因此整個聯合體的sizeof也就是每一個成員sizeof的最大值。
例子:
union u { int a; float b; double c; char d; }; sizeof(u); //值爲8
4. 數組的sizeof
數組的sizeof值等於數組所佔用的內存字節數。
注意:1)當字符數組表示字符串時,其sizeof值將’/0’計算進去。
2)當數組爲形參時,其sizeof值至關於指針的sizeof值。
例子1:
char a[10]; char n[] = "abc"; cout<<"char a[10] "<<sizeof(a)<<endl;//數組,值爲10 cout<<"char n[] = /"abc/" "<<sizeof(n)<<endl;//字符串數組,將'/0'計算進去,值爲4
例子2:
void func(char a[3]) { int c = sizeof(a); //c = 4,由於這裏a不在是數組類型,而是指針,至關於char *a。 } void funcN(char b[]) { int cN = sizeof(b); //cN = 4,理由同上。 }
5. 指針的sizeof
指針是用來記錄另外一個對象的地址,因此指針的內存大小固然就等於計算機內部地址總線的寬度。
在32位計算機中,一個指針變量的返回值一定是4。
指針變量的sizeof值與指針所指的對象沒有任何關係。
例子:
char *b = "helloworld"; char *c[10]; double *d; int **e; void (*pf)(); cout<<"char *b = /"helloworld/" "<<sizeof(b)<<endl;//指針指向字符串,值爲4 cout<<"char *b "<<sizeof(*b)<<endl; //指針指向字符,值爲1 cout<<"double *d "<<sizeof(d)<<endl;//指針,值爲4 cout<<"double *d "<<sizeof(*d)<<endl;//指針指向浮點數,值爲8 cout<<"int **e "<<sizeof(e)<<endl;//指針指向指針,值爲4 cout<<"char *c[10] "<<sizeof(c)<<endl;//指針數組,值爲40 cout<<"void (*pf)(); "<<sizeof(pf)<<endl;//函數指針,值爲4
6. 函數的sizeof
sizeof也可對一個函數調用求值,其結果是函數返回值類型的大小,函數並不會被調用。
對函數求值的形式:sizeof(函數名(實參表))
注意:1)不能夠對返回值類型爲空的函數求值。
2)不能夠對函數名求值。
3)對有參數的函數,在用sizeof時,須寫上實參表。
例子:
#include <iostream> using namespace std; float FuncP(int a, float b) { return a + b; } int FuncNP() { return 3; } void Func() { } int main() { cout<<sizeof(FuncP(3, 0.4))<<endl; //OK,值爲4,sizeof(FuncP(3,0.4))至關於sizeof(float) cout<<sizeof(FuncNP())<<endl; //OK,值爲4,sizeof(FuncNP())至關於sizeof(int) /*cout<<sizeof(Func())<<endl; //error,sizeof不能對返回值爲空類型的函數求值*/ /*cout<<sizeof(FuncNP)<<endl; //error,sizeof不能對函數名求值*/ return 0; }