不見得你會計算C字串長度
在 C 語言中,字串實際上是使用字元 '\0'
終止的一維字元陣列。
以下幾種方式表示的都是 C 字串。
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // 預設會在末尾增加'\0' char greeting[] = "Hello"; // 預設會在末尾增加'\0' char *greeting = "Hello";
看下面另外一種宣告方式:
char greeting[] = {'h', 'e', 'l', 'l', 'o'}; printf("greeting: %s\n", greeting);
輸出結果:
greeting: hello\376
這個結果在不同編譯器下面可能還會不一樣,無論如何輸出都不是我們想要的結果,這種方式建立的字串沒有 '\0'
,不算是真正的 C 字串,所以建議大家在宣告 C 字串的時候使用字元指標(char *)的方式。
string.h
裡面聲明瞭很多關於操作 C 字串的庫函式。
字串長度
在說如何計算字串長度之前,我們先來看一個例子。
char *greeting1 = "hello"; char greeting2[] = {'h', 'e', 'l', 'l', 'o'}; char greeting3[] = {'h', 'e', 'l', 'l', 'o', '\0'}; char greeting4[] = "hello"; printf("greeting1 sizeOf: %ld, strlen: %ld\n", sizeof(greeting1), strlen(greeting1)); printf("greeting2 sizeOf: %ld, strlen: %ld\n", sizeof(greeting2), strlen(greeting2)); printf("greeting3 sizeOf: %ld, strlen: %ld\n", sizeof(greeting3), strlen(greeting3)); printf("greeting4 sizeOf: %ld, strlen: %ld\n", sizeof(greeting4), strlen(greeting4));
如果你能說出上面 printf
的結果,基本上關於計算字串長度的問題就迎刃而解了。
上面例子的輸出結果如下所示:
greeting1 sizeOf: 8, strlen: 5 greeting2 sizeOf: 5, strlen: 7 greeting3 sizeOf: 6, strlen: 5 greeting4 sizeOf: 6, strlen: 5
如果輸出結果令你無法相信,可以繼續往下看,或者你自己寫程式碼試試。
sizeof、strlen
在 linux.die 可以查到 strlen 的說明,如下:
Synopsis: #include <string.h> size_t strlen(const char *s); Description: The strlen() function calculates the length of the string s, excluding the terminating null byte (aq\0aq). Return Value: The strlen() function returns the number of bytes in the string s.
函式 strlen
返回字串裡的字元數,不包括終止字元 '\0'
,這裡注意 strlen
是一個 C 的函式,而 sizeof
只是一個操作符。
我們知道, sizeof
操作符的引數可以是陣列、指標、型別、物件、函式等,函式 strlen
的引數只能是字串。
對於 sizeof
, 其引數不同時,其返回的值也不一樣,如下:
1、陣列:編譯時分配的陣列空間大小;
2、指標:儲存該指標所用的空間大小(32位機器上是4,64位機器上是8);
3、型別:該型別所佔的空間大小;
4、物件:物件的實際佔用空間大小(這個指的是在 C++ 中);
5、函式:函式的返回型別所佔的空間大小。函式的返回型別不能是void。
那我們再回頭看看上面的例子,我把要說明的寫在註釋上面了。
// 注意這裡是指標 char *greeting1 = "hello"; // 沒有結束符 '\0',其 strlen 結果不確定 char greeting2[] = {'h', 'e', 'l', 'l', 'o'}; char greeting3[] = {'h', 'e', 'l', 'l', 'o', '\0'}; char greeting4[] = "hello"; /* 結果是 8、5 */ /* greeting1是指標,sizeOf計算的是其儲存該指標所用的空間大小,因為我使用的是64位 macOS,所以輸出是8 */ /*strlen 計算的是字元個數但是不包括結束符 '\0'*/ printf("greeting1 sizeOf: %ld, strlen: %ld\n", sizeof(greeting1), strlen(greeting1)); /* 結果是 5、7 */ /* sizeof 計算的是編譯時分配的陣列空間大小,這裡是5 */ /* greeting2沒有結束符,strlen 的計算結果不確定 */ printf("greeting2 sizeOf: %ld, strlen: %ld\n", sizeof(greeting2), strlen(greeting2)); /* 結果是 6、5 */ /* sizeof 計算的是編譯時分配的陣列空間大小,這裡是6,因為多了結束符 */ /*strlen 計算的是字元個數但是不包括結束符 '\0'*/ printf("greeting3 sizeOf: %ld, strlen: %ld\n", sizeof(greeting3), strlen(greeting3)); /* 結果是 6、5,這裡類似上面的情況,不再贅述 */ printf("greeting4 sizeOf: %ld, strlen: %ld\n", sizeof(greeting4), strlen(greeting4));
小結:
1、 sizeof
是一個操作符,而 strlen
是 C 語言的庫函式。
2、 sizeof
的引數可以是任意資料型別或者表示式,而 strlen
只能以結尾為 '\0'
的字串作引數。
3、 sizeof
的結果在編譯時就計算出了,而 strlen
必須在執行時才能計算出來。
4、 sizeof
計算資料型別佔記憶體的大小, strlen
計算字串實際長度,要記住 strlen
計算出來的結果不包括結束符 '\0'
。
5、 sizeof
反應的並非真實字串長度而是所佔空間大小,所以 memset
初始化字串的時候用 sizeof
較好。
6、系統函式返回值是 char *
(字元指標)型別的會在末尾加上結束符 '\0'
。
我們還需要注意一點, strlen
函式,當陣列名作為引數傳入時,實際上陣列就退化成指標了。舉個例子,如下圖所示:
可以看出傳入進來的引數會被退化為指標。
掃碼關注,你我就各多一個朋友~