2010-12-12 68 views
3

我有一個基本的C編程問題,這裏是情況。如果我正在創建一個字符數組,並且如果我想使用%s轉換代碼將該數組視爲字符串,那麼我是否必須包含空零。例如:C字符串空零?

char name[6] = {'a','b','c','d','e','f'}; 
printf("%s",name); 

此控制檯輸出爲:

abcdef 

注意,沒有一個空零數組中的最後一個元素,但我仍然打印這是一個字符串。

我是新來的編程...所以我讀初學者ç書,其中規定,因爲我不是在最後一個元素使用空零,我不能把它當作一個字符串。

這與上面的輸出相同,儘管我包含了空零。

char name[7] = {'a','b','c','d','e','f','\0'}; 
printf("%s",name); 
+0

這是一些安全漏洞的來源。 – 2010-12-12 22:36:46

+1

+1我喜歡null零:)「那是什麼樣的零? 「零零。」 「長零。」 「一個浮動零點。」 「雙零。」 ... – pmg 2010-12-12 22:39:09

+2

一般情況下,你會這樣做的方式是'char name [7] =「abcdef」(在「」中的字符串字面量自動包含NUL) – 2010-12-12 22:41:48

回答

3

你的拳頭printf的輸出是不可預測的具體,因爲你沒有包括終止零字符。如果它在您的實驗中似乎有效,那只是因爲隨機偶然,內存中的下一個字節碰巧爲零,並且作爲零終止符工作。發生這種情況的可能性很大程度上取決於你聲明你的name數組的位置(這不清楚你的例子)。對於一個靜態數組來說,機會可能會非常高,而對於一個本地(自動)數組,你會碰到經常打印的各種垃圾。

+0

本質上,如果我想使用%s轉換,我必須添加一個空零「以確保」字符串正確終止? – Michael 2010-12-12 22:55:18

+0

是的(一般情況下,只要你想用'char'數組作爲C字符串就可以了);但是使用特殊的字符串初始化語法('char name [] =「abcdef」;',其中'NUL'自動添加,以及數組大小)更容易,而不是像這樣指定單個字符。 – 2010-12-12 23:04:03

+0

是的......這是我讀過的。非常感謝你! – Michael 2010-12-12 23:08:20

5

你只是幸運;大概在該數組結束後,在堆棧中,有一個零,所以printf在最後一個字符後停止讀取。如果你的程序非常短,堆棧區域仍然是「未開發」的 - 即堆棧還沒有增長到這一點 - 它很容易,它是零,因爲通常現代操作系統給應用程序初始化爲零頁。

更正式地說:由於沒有明確的終止符,你將進入未定義行爲的領域,這意味着任何事情都可能發生;這樣的任何事情也可能是你的程序工作正常,但這只是運氣 - 而且這是最糟糕的錯誤類型,因爲如果它一般工作正常,很難發現。

TL; DR版本:不這樣做。堅持保證工作,你不會在你的應用程序中引入偷偷摸摸的bug。

2

必須在末尾的空字符。

因爲運氣好運,沒有錯誤,只有運氣。試試這個:

char name[6] = {'a','b','c','d','e','f'}; 
printf("%s",name); 
printf("%d",name[6]); 

你最有可能看到的是你可以讀取內存,並有在它零。但這真是太幸運了。

+0

其實,如果你的程序「似乎有效」,當它做這樣糟糕的事情時,你是相當** **幸運的,因爲這使得它更難找到該程序。當然,只有當你寫了更多(正確)的代碼時,它纔會在後面大打出手,現在問題似乎完全不同了。或者它會爲你「工作」,當你向一個重要的人展示你的程序時會炸燬。或者...你有這個想法:) – 2010-12-13 08:14:51

+0

啊,爲你工作,但不在觀衆面前。經典。 – slezica 2010-12-13 16:43:00

0

最有可能發生的是,那裏恰巧0的存儲位置名稱+ 6這不是雖然定義的行爲的價值,你可以在不同的系統或不同的編譯器得到不同的輸出。

0

是的。你做。還有其他一些方法可以做到這一點。

這種形式的初始化,自動將NUL字符放入。

char name[7] = "abcdef"; 
printf("%s",name); 

請注意,我爲數組大小添加1,爲該NUL留出空間。

也可以省略大小,讓編譯器找出它。

char name[] = "abcdef"; 
printf("%s",name); 

另一種方法是用一個指向char的指針指定它。

char *name = "abcdef"; 
printf("%s",name); 
+0

我想補充一點,你指定的最後一個方法不等於前兩個:事實上,最後一個獲得一個指向內存只讀區域的指針,其中存儲字符「abcdef」(實際上是「 name'應該是一個'const char *'),另外兩個用這個值初始化一個數組,這樣的數組可以被修改而沒有問題。 – 2010-12-12 23:30:10

+0

是的,好點。當我是一個小孩時,你可以修改它們。 – EvilTeach 2010-12-13 00:36:31