sizeof的使用以及sizeof與strlen的區別

sizeof 是判斷數據類型長度符(字節數)的關鍵字。是一個操作符不是函數。

sizeof的用法:

sizeof(類型說明符,數組名或表達式);
  或sizeof 變量名

sizeof定義

sizeof是C/C++中的一個操作符(operator),簡單的說其作用就是返回一個對象或者類型所佔的內存字節數。

基本數據類型的sizeof
這裏的基本數據類型指short、int、long、float、double這樣的簡單內置數據類型,由於它們都是和系統相關的,所以在不同的系統下取值可能不同,這務必引起我們的注意,儘量不要在這方面給自己程序的移植造成麻煩。
一般的,在32位編譯環境中,sizeof(int)的取值爲4。
指針變量的sizeof
學過數據結構的你應該知道指針是一個很重要的概念,它記錄了另一個對象的地址。既然是來存放地址的,那麼它當然等於計算機內部地址總線的寬度。所以在32位計算機中,一個指針變量的返回值必定是4(注意結果是以字節爲單位),但是,在64位系統中指針變量的sizeof結果爲8。
char*pc="abc";
int*pi;
string *ps;
char**ppc=&pc;
void(*pf)();//函數指針
sizeof(pc);//結果爲4
sizeof(pi);//結果爲4
sizeof(ps);//結果爲4
sizeof(ppc);//結果爲4
sizeof(pf);//結果爲4
指針變量的sizeof值與指針所指的對象沒有任何關係,正是由於所有的指針變量所佔內存大小相等,所以MFC消息處理函數使用兩個參數WPARAM、LPARAM就能傳遞各種複雜的消息結構(使用指向結構體的指針)。
數組的sizeof
數組的sizeof值等於數組所佔用的內存字節數,如:
char a1[] = "abc"; int a2[3]; sizeof( a1 ); // 結果爲4,字符末尾還存在一個NULL終止符 sizeof( a2 ); // 結果爲3*4=12(依賴於int)
一些朋友剛開始時把sizeof當作了求數組元素的個數,如今你應該知道這是不對的,那麼應該怎麼求數組元素的個數呢Easy,通常有下面兩種寫法:
1
2
intc1=sizeof(a1)/sizeof(char);//總長度/單個元素的長度
intc2=sizeof(a1)/sizeof(a1[0]);//總長度/第一個元素的長度
寫到這裏,提一問,下面的c3,c4值應該是多少呢
1
2
3
4
5
6
7
8
voidfoo3(char a3[3])
{
int c3=sizeof(a3);//c3==
}
voidfoo4(char a4[])
{
int c4=sizeof(a4);//c4==
}
也許當你試圖回答c4的值時已經意識到c3答錯了,是的,c3!=3。這裏函數參數a3已不再是數組類型,而是蛻變成指針,相當於char* a3,爲什麼仔細想想就不難明白,我們調用函數foo3時,程序會在棧上分配一個大小爲3的數組嗎不會!數組是“傳址”的,調用者只需將實參的地址傳遞過去,所以a3自然爲指針類型(char*),c3的值也就爲4。
  


sizeof與strlen的區別
與strlen區別
strlen(char*)函數求的是字符串的實際長度,它求得方法是從開始到遇到第一個'\0',如果你只定義沒有給它賦初值,這個結果是不定的,它會從aa首地址一直找下去,直到遇到'\0'停止。
char aa[10];cout<<strlen(aa)<<endl; //結果是不定的 char aa[10]={'\0'}; cout<<strlen(aa)<<endl; //結果爲0 char aa[10]="jun"; cout<<strlen(aa)<<endl; //結果爲3=
而sizeof()函數返回的是變量聲明後所佔的內存數,不是實際長度。
sizeof(aa) 返回10 int a[10]; sizeof(a) 返回40
1.sizeof操作符的結果類型是size_t,它在頭文件中typedef爲unsigned int類型。
該類型保證能容納實現所建立的最大對象的字節大小。
2.sizeof是算符,strlen是函數。
3.sizeof可以用類型做參數,strlen只能用char*做參數,且必須是以''\0''結尾的。
sizeof還可以用函數做參數,比如:
1
2
shortf();
printf("%d\n",sizeof(f()));
輸出的結果是sizeof(short),即2。
4.數組做sizeof的參數不退化,傳遞給strlen就退化爲指針了。
5.大部分編譯程序在編譯的時候就把sizeof計算過了是類型或是變量的長度這就是sizeof(x)可以用來定義數組維數的原因
1
2
3
charstr[20]="0123456789";
inta=strlen(str);//a=10;
intb=sizeof(str);//而b=20;
6.strlen的結果要在運行的時候才能計算出來,是用來計算字符串的長度,不是類型佔內存的大小。
7.sizeof後如果是類型必須加括弧,如果是變量名可以不加括弧。這是因爲sizeof是個操作符不是個函數。
8.當適用於一個結構類型時或變量, sizeof 返回實際的大小,當適用於靜態的空間數組, sizeof 歸還全部數組的尺寸。
sizeof 操作符不能返回被動態分派的數組或外部數組的尺寸
9.數組作爲參數傳給函數時傳的是指針而不是數組,傳遞的是數組的首地址,
如:
1
fun(char[8])fun(char[])
都等價於 fun(char *)
特別注意:
1.sizeof是運算符,strlen是函數,具體如下:
sizeof
strlen
頭文件:stddef.h格式:1) sizeof( object ); // sizeof( 對象 );
2) sizeof( type_name ); // sizeof( 類型 );
3) sizeof object; // sizeof 對象
功能:一個對象或者類型所佔的內存字節數;
說明:sizeof操作符的結果類型是size_t,typedef unsigned int size_t;
原型:extern unsigned int strlen(char *s);頭文件:string.h
格式:strlen (字符數組名)
功能:計算字符串s的(unsigned int型)長度,不包括'\0'在內
說明:返回s的長度,不包括結束符NULL。
2.strlen只能用char*做參數,且必須是以''\0''結尾的,而sizeof可用類型做參數,還可用函數做參數,如:
1
2
intsum();
printf("%d\n",sizeof(sum()));//輸出的結果是sizeof(int),即4。
3.數組做sizeof的參數不退化,傳遞給strlen就退化爲指針了。
4.大部分編譯程序,sizeof在編譯時確定,因此sizeof(x)可以用來定義數組維數;而strlen要在運行時才能計算出來,用來計算字符串的長度,而不是類型佔內存的大小;
1
2
3
charstr[20]="0123456789"; 
intlen1=strlen(str);//len1=10; 
intlen2=sizeof(str);//len2=20;
5.sizeof後,若爲類型必須加括弧,若爲變量名可以不加括弧。這是因爲sizeof是個操作符不是個函數。
  6.當適用於一個結構類型時或變量, sizeof 返回實際的大小;當適用一靜態地空間數組,sizeof 歸還全部數組的尺寸。
  sizeof 操作符不能返回動態地被分派了的數組或外部的數組的尺寸;
  7.數組作爲參數傳給函數時傳的是指針而不是數組,傳遞的是數組的首地址,
  如:
1
2
fun(char[8]) 
fun(char[])
都等價於 fun( char * ) 
  在C++裏參數傳遞數組永遠都是傳遞指向數組首元素的指針,編譯器不知道數組的大小,如果想在函數內知道數組的大小, 需要這樣做:
  進入函數後用memcpy拷貝出來,長度由另一個形參傳進去
1
2
3
4
5
fun(unsigedchar*p1,intlen) 
{
unsignedchar*buf=newunsignedchar[len+1];
memcpy(buf,p1,len);
}
常在用到 sizeof 和 strlen 的時候,通常是計算字符串數組的長度,如果是對指針,結果則會不一樣的:
  char* str = "abacd";
  sizeof(str) //結果 4 --->str是指向字符串常量的字符指針,sizeof 獲得的是一個指針所佔的空間,應該是長整型的,所以是4;
  sizeof(*str) //結果 1 --->*str是第一個字符,其實就是字符串的第一位'a' 所佔的內存空間,是char類型的,佔了 1 位;
  strlen(str)= 5 //--->若要獲得這個字符串的長度,則一定要使用 strlen
在C++裏參數傳遞數組永遠都是傳遞指向數組首元素的指針,編譯器不知道數組的大小
如果想在函數內知道數組的大小, 需要這樣做:
進入函數後用memcpy拷貝出來,長度由另一個形參傳進去
1
2
3
4
5
fun(unsigedchar*p1,intlen)
{
unsignedchar*buf=newunsignedchar[len+1];
memcpy(buf,p1,len);
}
我們經常使用 sizeof 和 strlen 的場合,通常是計算字符串數組的長度
看了上面的詳細解釋,發現兩者的使用還是有區別的,從這個例子可以看得很清楚:
1
charstr[20]="0123456789";
int a=strlen(str); //a=10; >>>> strlen 計算字符串的長度,以結束符 0x00 爲字符串結束。
int b=sizeof(str); //而b=20; >>>> sizeof 計算的則是分配的數組str[20] 所佔的內存空間的大小,不受裏面存儲的內容改變。
上面是對靜態數組處理的結果,如果是對指針,結果就不一樣了
char* ss = "0123456789";
sizeof(ss) 結果 4 ===》ss是指向字符串常量的字符指針,sizeof 獲得的是一個指針的之所佔的空間,應該是
長整型的,所以是4
sizeof(*ss) 結果 1 ===》*ss是第一個字符其實就是獲得了字符串的第一位'0' 所佔的內存空間,是char類
型的,佔了 1 個字節
strlen(ss)= 10 >>>> 如果要獲得這個字符串的長度,則一定要使用 strlen
sizeof返回對象所佔用的字節大小. //正確
strlen返回字符個數. //正確
在使用sizeof時,有一個很特別的情況,就是數組名到指針蛻變,
1
2
3
4
charArray[3]={'0'};
sizeof(Array)==3;
char*p=Array;
strlen(p)==1;//sizeof(p)結果爲4
在傳遞一個數組名到一個函數中時,它會完全退化爲一個指針
----------------------------------------------------------
看完以上你是否很清楚sizeof和strlen的區別了呢?還不明白的話,我們看下面幾個例子:
第一個例子
1
char*ss="0123456789";
sizeof(ss) 結果 4 ===》ss是指向字符串常量的字符指針
sizeof(*ss) 結果 1 ===》*ss是第一個字符
大部分編譯程序 在編譯的時候就把sizeof計算過了 是類型或是變量的長度
這就是sizeof(x)可以用來定義數組維數的原因
1
2
3
charstr[20]="0123456789";
inta=strlen(str);//a=10;
intb=sizeof(str);//而b=20;
大部分編譯程序 在編譯的時候就把sizeof計算過了 是類型或是變量的長度
這就是sizeof(x)可以用來定義數組維數的原因
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
charstr[20]="0123456789";
inta=strlen(str);//a=10;
intb=sizeof(str);//而b=20;
charss[]="0123456789";
sizeof(ss)結果11===》ss是數組,計算到\0位置,因此是10+1
sizeof(*ss)結果1===》*ss是第一個字符
charss[100]="0123456789";
sizeof(ss)結果是100===》ss表示在內存中的大小100×1
strlen(ss)結果是10===》strlen是個函數內部實現是用一個循環計算到\0爲止之前
intss[100]="0123456789";
sizeof(ss)結果400===》ss表示在內存中的大小100×4
strlen(ss)錯誤===》strlen的參數只能是char*且必須是以'\0'結尾的
charq[]="abc";
charp[]="a\n";
sizeof(q),sizeof(p),strlen(q),strlen(p);
結果是 4 3 3 2
第三個例子
1
charszPath[MAX_PATH]
如果在函數內這樣定義,那麼sizeof(szPath)將會是MAX_PATH,但是將szPath作爲虛參聲明時
1
(voidfun(charszPath[MAX_PATH]))
sizeof(szPath) 卻會是4(指針大小)
還有一位網友的說明也很好:
其實理解 sizeof 只需要抓住一個要點:棧
程序存儲分佈有三個區域:棧、靜態和動態。能夠從代碼直接操作的對象,包括任何類型的變量指針,都是在棧上的;動態和靜態存儲區是靠棧上的所有指針間接操作的。 sizeof 操作符,計算的是對象在棧上的投影體積;記住這個就很多東西都很清楚了。
1
2
3
4
5
6
7
8
charconst*static_string="Hello";
//sizeof(static_string)是sizeof一個指針,所以在32bitsystem是4
charstack_string[]="Hello";
//sizeof(stack_string)是sizeof一個數組,所以是6*sizeof(char)
char*string=newchar[6];
strncpy(string,"Hello",6");
//sizeof(string)是sizeof一個指針,所以還是4。
//和第一個不同的是,這個指針指向了動態存儲區而不是靜態存儲區。
不管指針指向的內容在什麼地方,sizeof 得到的都是指針的棧大小
C++ 中對引用的處理比較特殊;sizeof 一個引用得到的結果是 sizeof 一個被引用的對象的大小;所以
1
2
3
4
5
6
7
8
9
10
11
structtest
{
inta,b,c,d,e,f,g,h;
};
intmain()
{
test&r=*newtest;
cout<<sizeof(test)<<endl;//32
cout<<sizeofr<<endl;//也是32
system("PAUSE");
}
r 引用的是整個的 test 對象而不是指向 test 的指針,所以 sizeof r 的結果和 sizeof test 完全相同。



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