我目前正在學習 C,我撰寫了這個程式來檢查 '\0' 字符是否真的在字串的末尾,如“K 和 R”中所指出的。
我得到了最奇怪的結果。
如果我評論“int lista[] = {0, 1, 2, 3, 4};” 程式外的陳述句(這是一個與該程式的其他陳述句無關的陳述句,它是我將要進行的另一個測驗的一部分)。程式的輸出結果如何,檢測到一個以字串結尾的 '\0' 字符。但是,如果我不注釋該陳述句,程式輸出將檢測到字串末尾的兩個 '\0'字符。為什么會發生這種情況?
這是陳述句未注釋的程式:
#include <stdio.h>
int main(void)
{
int lista[] = {0, 1, 2, 3, 4};
char string[] = "linhas";
for (int i = 0; i <= sizeof(string); i )
{
if (string[i] != '\0')
{
printf("%c\n", string[i]);
}
else
{
printf("this dawmn null char\n");
}
}
}
這輸出:
l
i
n
h
a
s
this dawmn null char
this dawmn null char
這是該行注釋掉的程式:
#include <stdio.h>
int main(void)
{
/*int lista[] = {0, 1, 2, 3, 4};*/
char string[] = "linhas";
for (int i = 0; i <= sizeof(string); i )
{
if (string[i] != '\0')
{
printf("%c\n", string[i]);
}
else
{
printf("this dawmn null char\n");
}
}
}
它輸出:
l
i
n
h
a
s
this dawmn null char
uj5u.com熱心網友回復:
你的回圈
for (int i = 0; i <= sizeof(string); i )
總是有點錯誤。它應該是
for (int i = 0; i < sizeof(string); i )
通過使用<=,您在回圈中進行了過多的旅行,并且您訪問了string陣列之外的記憶體。看起來,lista陣列就位后,您錯誤訪問的額外位元組(string陣列外)恰好是 0,因此您會得到“this dawmn null char”訊息的額外第二次列印輸出。
但是,當您注釋掉lista陣列時,一定是您錯誤訪問的額外位元組不是 0,因此它會被列印為本身。它可能是一個不可見的控制字符,這就是為什么你什么都看不到的原因。我建議將您的代碼更改為
if (string[i] != '\0')
printf("string contains %d\n", string[i]);
else printf("this damn null char\n");
更清楚地看到這一點。
這里的重要教訓是,如果您有一個應該運行 N 次的回圈,有兩種撰寫它的方法。在 C 中,絕大多數時候,你想把它寫成
for(i = 0; i < N; i )
這是一個“基于 0”的回圈,從 0 到 N-1,總共 N 趟。偶爾,您需要一個基于 1 的回圈:
for(i = 1; i <= N; i )
這從 1 到 N 運行,同樣總共有 N 趟。但是如果你寫
for(i = 0; i <= N; i ) /* usually WRONG */
您的回圈從 0 運行到 N,總共 N 1 趟。
uj5u.com熱心網友回復:
不要混淆strlen(string)在您的情況下應該是哪個6,sizeof(string)哪個是包括'\0'位元組在內的陣列的大小!;-)
在宣告為具有“自動大小”的陣列的字串的情況下,差異僅為一個,但如果您有char string[256],則sizeof(string)不會與 has 相同strlen(string) 1。
隨著char *string,sizeof(string)可能是8或4。
uj5u.com熱心網友回復:
@SteveSummit 已經詳細解釋了一切。這是一個簡短的答案。
訪問元素lista[sizeof(lista)]是未定義的行為,因此討論它應該具有什么值是“毫無意義的”。我參考了毫無意義的內容,因為了解未定義行為如何為除錯目的而表現出來可能是一件好事。但是,如果此代碼要投入生產,則永遠不要訪問lista[sizeof(lista)]. 它總是越界,總是一個錯誤。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/369514.html
