[英]C Programming - Functionality of strlen
我正在嘗試理解一些字符串函數,以便我可以在以后的編碼項目中更有效地使用它們,所以我在下面設置了簡單的程序:
#include <stdio.h>
#include <string.h>
int main (void)
{
// Declare variables:
char test_string[5];
char test_string2[] = { 'G', 'O', '_', 'T', 'E', 'S', 'T'};
int init;
int length = 0;
int match;
// Initialize array:
for (init = 0; init < strlen(test_string); init++)
{ test_string[init] = '\0';
}
// Fill array:
test_string[0] = 'T';
test_string[1] = 'E';
test_string[2] = 'S';
test_string[3] = 'T';
// Get Length:
length = strlen(test_string);
// Get number of characters from string 1 in string 2:
match = strspn(test_string, test_string2);
printf("\nstrlen return = %d", length);
printf("\nstrspn return = %d\n\n", match);
return 0;
}
我希望看到回歸:
strlen return = 4 strspn return = 4
但是,我看到strlen return = 6和strspn return = 4.據我所知,char test_string [5]應該分配5個字節的內存並將十六進制00放入第五個字節。 for循環(甚至不應該是nessecary)然后應該將test_string的所有內存字節設置為十六進制00.然后,緊接着的行應該填充test_string字節1到4(或test_string [0]到test_string [3])用我指定的。 此時調用strlen應該返回一個4,因為它應該從字符串0的地址開始並計算一個增量,直到它到達第一個空字符,即字符串[4]。 然后strlen返回6.任何人都可以解釋這個嗎? 謝謝!
char test_string[5];
test_string
是一個包含5個未初始化的 char
對象的數組。
for (init = 0; init < strlen(test_string); init++)
KABOOM。 strlen
掃描第一個'\\0'
0'null字符。 由於test_string
的內容是垃圾,因此行為未定義。 如果碰巧test_string
字符,它可能返回一個小值,如果test_string
沒有任何零字節,它可能返回一個大值或程序崩潰。
即使不是這種情況,在for
循環的標題中評估strlen()
也是低效的。 每個strlen()
調用都必須重新掃描整個字符串(假設你給它一個有效的字符串),所以如果你的循環工作,它將是O(N 2 )。
如果希望test_string
只包含零個字節,可以這樣初始化它:
char test_string[5] = "";
或者,因為您稍后初始化前4個字節:
char test_string[5] = "TEST";
要不就:
char test_string[] = "TEST";
(后者讓編譯器發現它需要5個字節。)
回到你的聲明:
char test_string2[] = { 'G', 'O', '_', 'T', 'E', 'S', 'T'};
這導致test_string2
長7個字節, 沒有尾隨'\\0'
字符。 這意味着將test_string2
傳遞給任何需要指向字符串的指針的函數都會導致未定義的行為。 你可能想要這樣的東西:
char test_string2[] = "GO_TEST";
strlen
搜索'\\ 0'字符來計算它們,在你的test_string中沒有,所以它會繼續,直到它找到一個恰好距離數組開頭6個字節的字符,因為它是未初始化的。
編譯器不會生成用於初始化數組的代碼,因此如果稍后填寫該代碼,則無需付費即可運行該代碼。
要將其初始化為0並跳過循環,您可以使用
char test_string[5] = {0};
這樣,所有字符都將初始化為0,並且在您使用“TEST”填充數組后,您的strlen將起作用。
這里有一些問題。 首先, char test_string[5];
只需為該字符串留出5個字節,但不將字節設置為任何字節。 特別是,當你說“char test_string [5]應該分配5個字節的內存並將十六進制00放入第五個字節 ”時,第二部分是錯誤的。
其次,你的數組初始化循環使用strlen(test_string)
但由於strlen(test_string)
的字節未初始化,因此無法知道是什么,因此strlen(test_string)返回一些未定義的結果。 清除數組的更好方法是memset( test_string, 0, sizeof(test_string) );
。
使用“TEST”填充數組但不在末尾設置NULL字節,因此最后一個字節仍未初始化。 如果你執行上面的memset,這將被修復,或者你可以手動執行test_string[4] = '\\0'
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.