Sizeof與Strlen的區別與聯繫

 

1.sizeof操作符的結果類型是size_t,它在頭文件中typedef爲unsigned int類型。
該類型保證能容納實現所建立的最大對象的字節大小。

2.sizeof是運算符,strlen是函數。

3.sizeof可以用類型做參數,strlen只能用char*做參數,且必須是以''\0''結尾的。
sizeof還可以用函數做參數,比如:
short f();
printf("%d\n", sizeof(f()));
輸出的結果是sizeof(short),即2。

4.數組做sizeof的參數不退化,傳遞給strlen就退化爲指針了。

5.大部分編譯程序在編譯的時候就把sizeof計算過了,看它是類型或是變量的長度,這就是sizeof(x)可以用來定義數組維數的原因。
char str[20]="0123456789";
int a=strlen(str); //a=10;
int b=sizeof(str); //而b=20;

6.strlen的結果要在運行的時候才能計算出來,主要用來計算字符串的長度,不是類型佔內存的大小。

7.sizeof後如果接類型參數必須加括弧,如果是變量名可以不加括弧。這是因爲sizeof是個操作符不是個函數。

8.當適用了於一個結構類型時或變量,sizeof 返回實際的大小,當適用一靜態地址空間數組,sizeof 歸還全部數組的尺寸。sizeof 操作符不能返回動態地被分派了的數組或外部的數組的尺寸。

9.數組作爲參數傳給函數時,傳遞的是指針而不是數組,傳遞的是數組的首地址,
如:
fun(char [8])
fun(char [])
都等價於 fun(char *)
在C++裏參數傳遞數組永遠都是傳遞指向數組首元素的指針,編譯器不知道數組的大小。如果想在函數內知道數組的大小,需要這樣做:
進入函數後用memcpy拷貝出來,長度由另一個形參傳進去
fun(unsiged char *p1, int len)
{
unsigned char* buf = new unsigned char[len+1]
memcpy(buf, p1, len);
}

我們能常在用到 sizeof 和 strlen 的時候,通常是計算字符串數組的長度。
看了上面的詳細解釋,發現兩者的使用還是有區別的,從這個例子可以看得很清楚:

char str[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。

strlen計算長度時,計算“\0”結束符之前的字符個數,“\n”算一個字符。

sizeof計算字符串長度時計算所有字符個數(結束符也算範圍內),“\0”“\n”都算一個字符。

一、sizeof的概念
sizeof是C語言的一種單目操作符,如C語言的其他操作符++、--等。它並不是函數。sizeof操作符以字節形式給出了其操作數的存儲大小。操作數可以是一個表達式或括在括號內的類型名。操作數的存儲大小由操作數的類型決定。其實可以簡單的理解sizeof是徵對"類型"的。

二、sizeof的使用方法 

1、用於數據類型 
 sizeof使用形式:sizeof(type)  數據類型必須用括號括住。如sizeof(int)。

2、用於變量 

sizeof使用形式:sizeof(var_name)或sizeof var_name 

變量名可以不用括號括住。如sizeof (var_name),sizeof var_name等都是正確形式。帶括號的用法更普遍,大多數程序員採用這種形式。 

注意:sizeof操作符不能用於函數類型,不完全類型或位字段。不完全類型指具有未知存儲大小的數據類型,如未知存儲大小的數組類型、未知內容的結構或聯合類型、void類型等。 

三、sizeof的結果

sizeof操作符的結果類型是size_t,它在頭文件中typedef爲unsigned int類型。該類型保證能容納實現所建立的最大對象的字節大小。

1、若操作數具有類型char、unsigned char或signed char,其結果等於1。因爲 ANSI C正式規定字符類型爲1字節。

2、int、unsigned int 、short int(short)、unsigned short 、long int(long) 、unsigned long 、float、double、long double類型的sizeof 在ANSI C中沒有具體規定,大小依賴於實現,一般可能分別爲2、2、2、2、4、4、4、8、10。

3、當操作數是指針時,sizeof依賴於編譯器。例如Microsoft C/C++7.0中,near類指針字節數爲2,far、huge類指針字節數爲4。一般Unix的指針字節數爲4。

4、當操作數具有數組類型時,其結果是數組的總字節數,特別要注意字符串數組,如:
Char str[]=“123456” sizeof(str)=7。

5、聯合類型操作數的sizeof是其最大字節成員的字節數。結構類型操作數的sizeof是這種類型對象的總字節數,包括任何墊補在內。
讓我們看如下結構: 
struct {char b; double x;} a; 
在某些機器上sizeof(a)=16,而一般sizeof(char)+ sizeof(double)=9。
這是因爲編譯器在考慮對齊問題時,在結構中插入空位以控制各成員對象的地址對齊。

6、如果操作數是函數中的數組形參或函數類型的形參,sizeof給出其指針的大小。
即:int func(char p[100])
{ sizeof(p) = 4; }
C/C++中不能傳數組,只能傳指針,所以任何數組都會隱式轉成指針形式進行操作,所以"類型"還是指針。

7.sizeof是運算符 當編譯器編譯時 會自動運算這個變量的大小的並使用它的大小代替sizeof的值如
int len = sizeof(int);編譯時 編譯器計算出int的大小 大小爲4 所以把上面這句變成
int len = 4

四、sizeof與其他操作符的關係
  sizeof的優先級爲2級,比/、%等3級運算符優先級高。它可以與其他操作符一起組成表達式。如i*sizeof(int);其中i爲int類型變量。

五、sizeof的主要用途

1、sizeof操作符的一個主要用途是與存儲分配和I/O系統那樣的例程進行通信。例如: 
  void *malloc(size_t size), 
  size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)。 
2、sizeof的另一個的主要用途是計算數組中元素的個數。例如: 
  void *memset(void *s,int c,sizeof(s))。

3.在動態分配一對象時,可以讓系統知道要分配多少內存。

如:int *p=(int *)malloc(sizeof(int)*10);

4.由於操作數的字節數在實現時可能出現變化,建議在涉及到操作數字節大小時用sizeof來代替常量計算。

5.如果操作數是函數中的數組形參或函數類型的形參,sizeof給出其指針的大小。

六、建議

  由於操作數的字節數在實現時可能出現變化,建議在涉及到操作數字節大小時用ziseof來代替常量計算。


下面我們來看看strlen()
一、strlen是函數

strlen只能用char*做參數,且必須是以''\0''結尾的。Strlen將返回它的長度,不包括‘\0’。

二、由幾個例子說開去。

第一個例子:
char* ss = "0123456789";
sizeof(ss) 結果 4 ===>ss是指向字符串常量的字符指針
sizeof(*ss) 結果 1 ===>*ss是第一個字符

char ss[] = "0123456789";
sizeof(ss) 結果 11 ===>ss是數組,計算到\0位置,因此是10+1
sizeof(*ss) 結果 1 ===>*ss是第一個字符

char ss[100] = "0123456789";
sizeof(ss) 結果是100 ===> ss表示在內存中的大小 100×1
strlen(ss) 結果是10 ===> strlen是個函數內部實現是用一個循環計算到\0爲止之前

int ss[100] = "0123456789";
sizeof(ss) 結果 400 ===>ss表示再內存中的大小 100×4
strlen(ss) 錯誤 ===>strlen的參數只能是char* 且必須是以''\0''結尾的

char q[]="abc";
char p[]="a\n";
sizeof(q),sizeof(p),strlen(q),strlen(p);
結果是 4 3 3 2

第二個例子:
class X{
int i;
int j;
char k;
};

X x;
cout<<sizeof(X)<<endl; 結果 12 ===>內存補齊
cout<<sizeof(x)<<endl; 結果 12 同上
(詳細可見另篇文章:由朗訊的一道筆試題想到的!)

第三個例子:
數組用作參數傳遞,見上面6
列出幾個重要的區別:
1.sizeof是算符,strlen是函數。
2.sizeof可以用類型做參數,strlen只能用char*做參數,且必須是以''\0''結尾的。
sizeof還可以用函數做參數,比如:
short f();
printf("%d\n", sizeof(f()));
輸出的結果是sizeof(short),即2。
3.strlen計算的是字符串的長度,sizeof計算的是變量使用的內存大小,不受裏面存儲的內容改變
4.strlen的結果要在運行的時候才能計算出來,時用來計算字符串的長度,不是類型佔內存的大小。
5.sizeof後如果是類型必須加括弧,如果是變量名可以不加括弧。這是因爲sizeof是個操作符不是個函數。
6.當適用了於一個結構類型時或變量, sizeof 返回實際的大小, 當適用一靜態地空間數組, sizeof 歸還全部數組的尺寸。 sizeof 操作符不能返回動態地被分派了的數組或外部的數組的尺寸。
6.數組作爲參數傳給函數時傳的是指針而不是數組,傳遞的是數組的首地址,如:
fun(char [8])
fun(char [])
都等價於 fun(char *)
在C++裏參數傳遞數組永遠都是傳遞指向數組首元素的指針,編譯器不知道數組的大小
如果想在函數內知道數組的大小, 需要這樣做:
進入函數後用memcpy拷貝出來,長度由另一個形參傳進去
fun(unsiged char *p1, int len)
{
unsigned char* buf = new unsigned char[len+1]
memcpy(buf, p1, len);
}
我們能常在用到 sizeof 和 strlen 的時候,通常是計算字符串數組的長度

好了看了上面的講解和例題,我們來測試幾個題:
1.不要上機測試,否則便沒有什麼意義。

如下程序的輸出是什麼?(在intel x86(32-bit) platform.)
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
int main( )
{
    char str[10];
    char *p;
   memset(str,0x00,sizeof(str));
    p = (char *)malloc(100);
    printf("%d\n",sizeof(p));
    printf("%d\n",sizeof('p'));
    printf("%d\n",strlen(str));
    exit(0);
}

答:4/1/0, 如果不加memset(),第三行就會打出15(隨機數),請問這是爲什麼?
memset函數是初始化分配的內存空間,使用0、0x00都是0,即‘\0',不同系統當分配一塊內存時,這塊內存中的內容是未知的,系統只是根據申請者的要求爲其劃一塊內存並不管他原先的內容是什麼(有的系統清零),所以你的是隨即數15。


2.你能夠正確的說出它們的sizeof和strlen的大小嗎?

#include <stdio.h>
#include<stdlib.h>
#include<string.h>
int main( )
{
    char *str1="absde";
    char str2[]="absde";
    char str3[8]={'a',};
    char str4[8]={'a','b','s','e','f','g','h','j'};

    printf("sizeof(str1)=%d\n",sizeof(str1));
    printf("sizeof(str2)=%d\n",sizeof(str2));
    printf("sizeof(str3)=%d\n",sizeof(str3));
    printf("sizeof(str4)=%d\n",sizeof(str4));

    printf("strlen(str1)=%d\n",strlen(str1));
    printf("strlen(str2)=%d\n",strlen(str2));
    printf("strlen(str3)=%d\n",strlen(str3));
    printf("strlen(str4)=%d\n",strlen(str4));

    exit(0);

}
答:sizeof是計算括號中變量的類型所佔的儲存空間(不考慮內容);strlen是計算變量值爲起點的內存地址到第一個'\0'的距離,以字節爲單位,字符串尾部爲'\0',0=='\0'(不包括’\0’)。正確答案是:4、6、8、8;5、5、1、9;

可能這個是在C語言裏面比較基礎的問題了,但是很多情況下是經常混淆的,必須下面的一組數據,你能夠正確的說出它們的sizeof和strlen的大小嗎?
char *str1="absde";
char str2[]="absde";
char str3[8]={'a',};
char str4[8]={'a','b','s','e','f','g','h','j'};


其實你只要掌握了兩者的意義,就很容易解了,這種題目在筆試的時候最容易出了。答案見下面:


sizeof(str1)=4;
sizeof(*str1)=1;
strlen(str1)=5;
sizeof(str2)=6;
strlen(str2)=5;
sizeof(str3)=8;
strlen(str3)=1;
sizeof(str4)=8;
strlen(str4)=13;
strlen(*str1) 出錯
passing arg1 of 'strlen' makes pointer from integer without a cast.

sizeof是計算括號中變量的類型所佔的儲存空間。
strlen(str4)有可能爲不小於8的其他數字,取決於內存中的數據,因爲 strlen是計算變量值爲起點的內存地址到第一個'%content%'的距離,以字節爲單位,字符串尾部爲'%content%',0=='%content%'.

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