字元與字串中的'\0', '0', 0;strlen()函式求字串長度計算方法(sizeof()驗證)
如下字元陣列or字串,用strlen函式求長度各是多少?
char * p = “abc” 與 char a[] = "abc"兩種形式並不同;
char * str1 = "abc"; char * str2 = "ab\0c"; char * str3 = "ab\\0c"; char * str4 = "abc0c"; char arr0[5] = {'1', '2', '3', '4', '5'}; char arr1[5] = {'1', '2', '3', '4', '\0'}; char arr2[5] = {'1', '2', '3', '4', 0}; char arr3[5] = {'0', '0', '0'}; char arr4[5] = {0, 'a', 'b'}; char arr5[5] = {'a', '\0', 'b'}; char arr6[5] = {'a', 0, 'b'};
答案為 3 2 5 5 未知 4 4 3 0 1 1
當然sizeof(arrx) x代表0 - 6 的結果都為5
sizeof(arrx[y]) x為0 - 6. y為 0 - 4都為1.
sizeof(strx) x為 1 - 4都為4. (32位平臺下,指標大小為4位元組)
為什麼呢? 首先,在字串中‘\0’代表空字元,‘\0’ASCII值為0. 所以可認為‘/0’ == 0.
strlen函式工作機理:函式從第一個字元開始計算字串中字元數,直到遇到空字元,然後返回空字元前字元總個數。
接下來分析:
char * str1 = “abc”;
3 字串"abc",沒什麼好說的,系統自動在末尾加上空字元。 所以為3.
char * str2 = “ab\0c”;
2 第一個字串"abc"相當於 “abc\0”,既然系統識別出了最後的空字元,說明系統把‘\0’當成一個整體,一個字元’\0’。而不是按照’'與’0’兩個字元對待。 所以遇到ab後的‘\0’時,strlen函式認為已經到了字串的結尾。
char * str3 = “ab\0c”;
5 此時第二個斜槓被第一個斜槓轉義,“\0“相當於字元’\’(第二個’‘被第一個’‘轉義為“列印” ‘’ 而不是把第二個 ‘’ 當成一個 轉義字元 和 0 合為’\0’)與字元’0’。
char * str4 = "abc0c"
5 雖然說過 ‘/0’ == 0 可在這裡, 字串中0, 代表字元’0’ 而不是數字0. 因此不終止strlen計算個數。
char arr0[5] = {‘1’, ‘2’, ‘3’, ‘4’, ‘5’};
不確定 這是一個字元陣列,他裡面存放的並不是字串 (因為無’\0’),只是一系列字元
因為最後無空字元,所以strlen一直尋找直到遇到第一個空字元,此時結果不可預知(幸運的是,記憶體中’\0’還是蠻多的)
比如我自己試了兩次,一次strlen( arr0[5] ) = 15,一次16
char arr1[5] = {‘1’, ‘2’, ‘3’, ‘4’, ‘\0’};
4 因為第五個元素為’\0’
char arr2[5] = {‘1’, ‘2’, ‘3’, ‘4’, 0};
4 因為數字0 == ‘\0’
char arr3[5] ={‘0’, ‘0’, ‘0’};
3 前三個元素為字元‘0’ != 數字0 (’\0’),因為部分初始化,陣列剩下元素被設定為數字0,因此第四個元素為0 == ‘\0’。終止,所以為3.(陣列聲明後不初始化,裡面值為隨機值,部分初始化後,未被初始化部分自動被初始化為0)
char arr[4] = {0, ‘a’, ‘b’};
0
char arr[5] = {‘a’, ‘\0’, ‘b’}
1
char arr[6] = {‘a’, 0, ‘b’};
1
小小總結一下:
1.字串和字元陣列的區別和聯絡:
C語言中沒有一個用於表示字串的關鍵字;
C語言的字串由C的字元陣列變形而成,末尾加上’\0’,即字串比字元陣列多一個’\0’;
要從記憶體分配角度分析請看另一篇博文:
https://www.cnblogs.com/yygsj/p/4996377.html
2.數字0,’\0’ ,字元0的關係:
在字串中‘\0’代表空字元,‘\0’ASCII值為數字0. 所以可認為‘\0’ == 0.
注意只有數字0才會被當做空字元’\0’哦,字元0(即’0’)還是不會被當做空字元的。
比如char *str = “abc0”,char str1[] = “abc0”;這裡字串"abc0"中的0會被當做字元0(即’0’),strlen()不終止;
再比如char str2[] = {‘a’, ‘b’, ‘c’, ‘0’},這個字元陣列str2就相當於字串str,strlen()函式求長度都是4;
再比如char str3[] = {‘a’, ‘b’, ‘c’, ‘\0’},char str4[] = {‘a’, ‘b’, ‘c’, 0};這倆是求長度是一樣的,原因就是上面的’\0’ 和 數字0均認為是空字元;
3.我們再來看看"abc\0d"這個字串,系統在d字元後還加空字元嗎? 它裡面已經有空字元了啊!?
系統還是會加的,因為系統只負責在引號中最後一個字元結尾加一個空字元,然後根據你佔用的空間大小以位元組為單位給字串開闢空間,它才不管你字串裡面有沒有空字元
( 按照約定,空字元代表字串結束,所以平時不要在字串內部加空字元 )
我們可以通過sizeof關鍵字來驗證,sizeof以位元組為單位返回所佔空間大小,包括空字元, 而strlen是計算長度直到遇到空字元停止,對他來說遇到空字元就停止工作。
如果系統在"abc\0d"末尾加空字元,那麼sizeof(“abc\0d”)的返回值應該為6(‘\0’當一個字元對待),不加則為5。經驗證為6,說明系統在最後是加空字元的(也說明了字串中的空字元並不起終止字串儲存的作用,系統只是把’\0’當字串中一個字元對待)。
sizeof(“abc\0”) == 5
sizeof(“abc\0\0”) == 6
sizeof"abc\0d") == 6
還想到一種驗證方法,針對"abc\0d"實現一個函式,函式遇到第二個空字元返回包括第二個空字元在內的字串字元總個數,即可以驗證系統在這個字串後還加沒加空字元。(如果加程式返回6,如果不加則不是6,是一個隨機值,or程式直接出錯)。
#include <stdio.h>
int MyFun (const char * str);
int main (void)
{
int n = MyFun("abc\0d");
printf ("%d\n", n);
return 0;
}
int MyFun (const char * str)
{
int i = 0;
int flag = 0;
while (1)
{
i++;
if ( *str++ == '\0' )
{
flag++;
}
if ( flag == 2 )
{
return i;
}
}
}