C語言中sizeof與strlen區別2

1. 以字符串形式出現的,編譯器都會爲該字符串自動添加一個0作爲結束符,如在代碼中寫"abc",那麼編譯器幫你存儲的是"abc\0".

2. 字符串直接量作爲字符指針的初始值 

  "hello"是一個字符串直接量,編譯器將其作爲const char*處理,與之相關聯的內存空間位於內存的只讀部分,即允許編譯器重用指向等價字符串直接量的引用以優化內存使用,

即使程序  中使用了字符串直接量500次,編譯器在內存中也只是創建了一個實例。例如: char *ptr = “hello”; 等價於 const char *ptr = “hello”;

字符串直接量"hello"關聯的是隻讀內存,如果試圖修改將出錯,例如ptr[1] = ‘a’;是會引起錯誤的。

3. 字符串直接量作爲基於棧的字符數組的初始值

    由於基於棧的變量不可能引用其他地方存儲的內存,編譯器會負責將字符串直接量複製到基於棧的數組內存中。

    例如: char stackArray[] = “hello”;

    做如下修改: stackArray[1] = ‘a’;是真確的。

4. 字符數組與字符指針

    字符數組的形式如下,會將字符直接量拷貝到棧上:

          char str[]   = "abc";             // 實際的數據存儲: a b c \0,也就是增加了一個終結符\0

          char str[3] = {'a','b','c'};     // 實際的數據存儲: a b c,並沒有在最後添加終結符

          char str[10] = {'a','b','c'};   // 實際的數據存儲: a b c \0 \0 \0 \0 \0 \0 \0

   字符指針的形式如下:

          char *str = “abc”;               // 實際的數據存儲: a b c \0,也就是增加了一個終結符\0

5. 類型的決定

    1). 數組的類型是由該數組所存放元素的類型以及數組本身的大小決定的

         如char s1[3]和char s2[4],s1的類型就是char[3],s2的類型就是char[4],也就是說盡管s1和s2都是字符數組,但兩者的類型卻是不同的。

    2). 字符串常量的類型可以理解爲相應字符常量數組的類型

         如"abcdef"的類型就可以看成是const char[7],也就是說實際的數據存儲爲"abcdef\0"。

    3). 函數參數列表中的以數組類型書寫的形式參數,編譯器把其解釋爲普通的指針類型

         如對於void func(char sa[100],int ia[20],char *p),則sa的類型爲char*,ia的類型爲int*,p的類型爲char*。

對於sizeof與strlen: 

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

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

3. sizeof可以用類型做參數,strlen只能用char*做參數,且必須是以''\0''結尾的。

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

5. 大部分編譯程序在編譯的時候就把sizeof計算過了,是類型或是變量的長度這就是sizeof(x)可以用來定義數組維數的原因。
    char str[20]="0123456789"; // str是編譯期大小已經固定的數組
     int a=strlen(str); //  a=10; //strlen()在運行起確定,計算的是實際長度
     int b=sizeof(str); //  而b=20; //sizeof()在編譯期確定,str的類型是int[20],計算的是佔據內存的大小

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

7. sizeof後如果是類型必須加括弧,如果是變量名可以不加括弧。這是因爲sizeof是個操作符不是個函數。
    char c;
    sizeof c;  //變量名可以不加括弧
8. 當適用於一個結構類型或變量, sizeof 返回實際的大小,
    當適用一靜態地空間數組, sizeof 歸還全部數組的尺寸。
    sizeof 操作符不能返回動態地被分派了的數組或外部的數組的尺寸

sizeof、strlen計算字符數組、字符指針空間

 

char str[] = "abc";  實際的數據存儲: a b c \0,也就是增加了一個終結符\0 其類型爲char[4]   VS: sizeof(str)=4     strlen(str) = 3
GCC: sizeof(str)=4     strlen(str) = 3
char str[]   = "abc"; 實際的數據存儲: a b c \0,也就是增加了一個終結符\0 其類型爲char[4]   VS: sizeof(str)=4     strlen(str) = 3
GCC: sizeof(str)=4     strlen(str) = 3
char str[] = {'a','b','c'}; 實際的數據存儲: a b c,並沒有在最後添加終結符 其類型爲char[3]   VS: sizeof(str)=3     strlen(str) = 15
GCC: sizeof(str)=3     strlen(str) = 6
char str[3] = {'a','b','c'}; 實際的數據存儲: a b c,並沒有在最後添加終結符 其類型爲char[3]   VS: sizeof(str)=3     strlen(str) = 15
GCC: sizeof(str)=3     strlen(str) = 6
char str[5] = {'a','b','c','d','e'};  實際的數據存儲: a b c d e ,並沒有在最後添加終結符 其類型爲char[5]   VS: sizeof(str)=5     strlen(str) = 19
GCC: sizeof(str)=5     strlen(str) = 8

char str[5] = {'a','b','c','d'};

實際的數據存儲: a b c d \0(默認填充字符\0) 其類型爲char[5]   VS: sizeof(str)=5     strlen(str) = 4
GCC: sizeof(str)=5     strlen(str) = 4
char *pstr = "abcde"; 實際的數據存儲: a b c d e \0 pstr的類型爲char* sizeof(pstr) = 4 ( 指針的數據存儲空間,4個字節),strlen(pstr) = 5

總結一下:

1). sizeof的結果是類型的大小,區分類型之後,sizeof的結果也就命了,sizeof的結果是在編譯期決定的,計算的佔據的內存大小。

     srelen的結果是在運行期間決定,計算的是實際長度,strlen只能以char*作參數,以\0作爲結束符, 以上的例子中,紅色部分的strlen計算是錯誤的,

     因爲在str的數據存儲中並沒有 一個\0字符,所以strlen的結果看似有點異常。

2). 注意在計算sizeof的時候:

     char str[] = "abc";  類型爲char[4],   sizeof(str) = 4*sizeof(char) = 4.

3). sizeof(express),其中的express在編譯過程中是不會被編譯的,而是被替代類型。

     例如: int a = 1; sizeof(a=2);

     此時的express爲a=2,在編譯過程中被替換爲sizeof(int),所以在執行完之後,a仍然是等於1.

4). 對函數使用sizeof,在編譯階段會被替換爲函數的返回值的類型取代

     例如: int f(){return 0;}  sizeof(f());的結果爲4.

             void f(){}            sizeof(f());編譯過程中會出現錯誤,替換之後的sizoeof(void)編譯無法通過.

原文參見:http://www.cnblogs.com/alex-tech/archive/2011/03/26/1996284.html

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