2017-02-22 97 views
-2

我在C中初始化一個字符串(字符數組),我注意到即使我在字符串中輸入了第二個空字符(\ 0),它將被忽略並且不會返回任何錯誤。看下面我的意思是:在字符串中忽略第二個空字符

#include <stdio.h> 

int main() 
{ 
    char word[]= {'H','e','l','l','o','\0','\0'}; 
    char word2[]= "Hello\0\0"; 
    printf("Word is : %s\n",word);  // Prints "Hello" 
    printf("Word 2 is : %s\n",word2); // Prints "Hello" as well 

    return 0; 
} 

你能解釋一下爲什麼嗎?

+1

第二種情況'word2 []'實際上有*三個* nul字符:你放在那裏的兩個,編譯器放在那裏的那個。 –

+0

倒票的原因是什麼? – Dchris

+1

可能是因爲你沒有顯示任何研究工作?在提問之前閱讀C書,這是基本的東西。 – Olaf

回答

4

在C中,「字符串」定義爲由nul結尾的非nul字符序列。所以第二個nul不是字符串的一部分。第一個nul標記結束 - 這就是printf知道在使用%s格式說明符時要打印多少個字符。

+1

雖然它是數組的一部分,那完全正確。 –

+0

@IharobAlAsimi所以,它是數組的一部分,但不是字符串的一部分? – Dchris

+1

正確。考慮'char j [100];'然後'strcpy(j,「hi」);'。這裏,'j'是數組中100個字節的東西。它還包含字符串「hi」,它是兩個字符和一個終止nul。大數組作爲容器容納較小的字符串(以及其他一些東西)。 –

3

不確定你的預期。

任何以結尾的字符數組都是字符串。由於字符串已結束,字符串結尾後的內容無關緊要。

這也沒關係:

const char *two = "hello\0there"; 

printf("%s\n", two); 

這將打印

hello 

嵌入式'\0'後的字符並不重要,他們不是字符串的一部分開始於two這樣的當然printf()不在乎。

你可以把剩餘的字符作爲一個字符串太,當然:

printf("%s\n", two + 6); 

這將打印

there 

下半年以來也是一個有效的字符串(雙引號的文字像這添加終結者)。所以two包含兩個字符串,這是我的觀點。

+0

很好的例子,謝謝! – Dchris

2

NUL字符(如果您正在閱讀C標準,則爲空字符)終止C字符串。這是一個指標,所以你不需要拖動字符串的大小。並且沒有任何東西排除其他值放在緩衝區之後,包括其他NUL字符。事實上,C標準庫甚至具有破壞性的strtok函數,該函數將該字符放入字符串中作爲「標記化」的一部分。

+3

@TonyTannous我們很感謝你,因爲你錯了。 –

+0

@IharobAlAsimi好的我想要一個解釋:) –

+1

@TonyTannous - NULL是常量,NUL是我們用來避免混淆的常用縮寫https://en.wikipedia.org/wiki/Null_character – StoryTeller

1

C中的大多數字符串操作(例如printf)知道何時停止讀取一個字符串,一旦它找到NULL終止符。它在那一刻停止搜索。其實printf並不是用來打印NULL終止符的。 C中的所有字符串都以一個結束,所以如果打印出來,每個字符串在輸出中都會有'\ 0'。這將是非常沒有意義的。

0

實際上你的第二個數組中有3 '\0' s。但請注意,'\0'或ascii nul被認爲是c中字符串的分隔符,事實上,正如其他人在c中所說的,字符串只不過是字節序列,後面跟着一個字節'\0'

因此,你認爲應該用「多餘的'\0'來完成某件特別的事情是錯誤的。其實,我說「額外」,因爲即使他們是陣列的一部分,他們不是字符串的一部分,並確保你可以嘗試

char string[] = "Example\0Example"; 

,你會看到,整個「 示例「在'\0'之後將不會打印,如果您使用printf(),也不會通過strlen()或任何str * funcion來考慮。此外,原則上它具有明確插入的內容,並且在第二個「示例」之後隱含地添加另一個。

+0

我保持「ascii nul被認爲是C中的字符串的分隔符」,並且「也不會被strlen()或任何str * funcion考慮到」。有用的提示。謝謝 – Dchris

1

二空字符字符串

忽略不,它不會被忽略。如果你運行這個程序示範

#include <stdio.h> 

int main(void) 
{ 
    char word[]= {'H','e','l','l','o','\0','\0'}; 
    char word2[]= "Hello\0\0"; 

    printf("sizeof(word) = %zu\n", sizeof(word)); 
    printf("sizeof(word2) = %zu\n", sizeof(word2)); 
} 

您將得到以下結果

sizeof(word) = 7 
sizeof(word2) = 8 

這是所有零字符被列入字符數組。

考慮到字符串文字也包含不可見的空終止字符。那就是這個字符串文字"Hello\0\0"(類型爲char[8])被存儲在內存中,如{ 'H', 'e', 'l', 'l', 'o', '\0', '\0', '\0' }

冗餘零字符由一些功能,如例如忽略功能strlen或功能printf在格式說明%s被使用,因爲這些功能考慮字符數組爲包含字符串是由零字符分隔的字符序列。

此外,您可以使用零初始化字符數組的所有元素。例如

char s[5] = { '\0' }; 

此聲明等效於

char s[5] = { '\0', '\0', '\0', '\0', '\0' }; 

或者你甚至可以寫

char s[] = "\0\0\0\0"; 

其實這個聲明等效於數組s以前的聲明是數組將包含5零個字符。

如果執行該語句

printf("%zu\n", sizeof(s)); 

你會得到預期5。但是,如果你執行該語句

printf("%zu\n", strlen(s)); 

或本聲明

printf("%s\n", s); 

你會得到0或(在第二種情況下)不會顯示任何內容,除了光標將在下一行移動..

+0

有用的提示。謝謝。 – Dchris