2012-05-24 23 views
5

所以我做了如下試驗:包含' 0'的字符串文字 - 爲什麼它們不一樣?

char* a = "test"; 
char* b = "test"; 
char* c = "test\0"; 

而現在的問題:

1)能夠保證所有的a==b我知道我在比較地址。這並不意味着要比較字符串,但相同的字符串文字是否存儲在單個內存位置

2)爲什麼不是a==c?編譯器不應該看到它們指的是相同的字符串嗎?

3)c的末尾是否附加了\0,即使它已經包含了一個?

我不想問這3個不同的問題,因爲他們似乎有點相關,對不起'布特那。

注:標籤是正確的,我對C++感興趣。 (雖然請說明C的行爲是否不同)

+7

應該是'char const * a = ...'。 –

+0

a和b具有相同的值,但這並不一定意味着它們是_same_字符串。 –

+0

@HunterMcMillen - 其實這就是它的意思。 –

回答

18

是否保證a == b?

號但它是由§2.14.5/ 12允許:

是否所有字符串文字是不同的(即,被存儲在非重疊的對象)是實現定義。試圖修改字符串文字的效果是未定義的。

而且,你可以使用char*代替char const*最後一句看到的是一個麻煩的食譜(和你的編譯器應該拒絕它,請確保您有打開了警告,並選擇高一致性水平)。

爲什麼不是a == c?編譯器不應該看到它們指的是相同的字符串嗎?

不,他們不需要指的是相同的字符數組。一個有五個要素,另外六個要素。一個實現可以將這兩個存儲在重疊存儲中,但這不是必需的。

在c的末尾添加了一個\ 0,即使它已經包含了一個?

是的。

+0

也許值得說明的是''test''是一個文字'char const [5]'在A和B *爲什麼會重疊但C不會的背景下。 – AJG85

+0

謝謝。還有一個問題。如果我用'strcmp'比較'a'和'c',它會說它們是否相等?另外,是否允許'a == c'? – AMCoder

+0

@ AJG85爲什麼不會'c'重疊?標準明確地允許它(引用在答案中,並且不限於相同的文字),並且程序不能在不調用未定義的行爲的情況下區分差異。 –

6

1 - 絕對不是。如果編譯器選擇共享相同的靜態字符串,則可能會出現一個== == b。

2 - 因爲它們不是指相同的字符串

3 - 是的。

這裏的C和C++的行爲沒有什麼不同,只是C++編譯器應該拒絕賦值給非const char *。

+0

字符串文字轉換爲char *轉換已被棄用,但在C++中不被禁止。 –

+0

@james它在C++中被禁止11 –

+0

@ JohannesSchaub-litb:沒辦法!這是我一整天聽到的最好的消息。 g ++ 4.7,clang 3.1和VC11都接受這種轉換,但我期待他們不會這樣做:-) –

2

這裏的問題是你在混合指針和文本等價的概念。

當你說a == ba == c你問的指針是否指向相同的物理地址。測試與指針的文本內容無關。

爲了讓文字等價,你應該使用strcmp

+0

請注意'strcmp'會停止在* first *零,所以字符串'a'和'c'會比較相等,即使一個比另一個長。 –

+0

@MarkRansom它在文本意義上的等效長度,儘管這是strcmp會考慮的。也許我應該擴大我的答案到這裏可能很重要的三個領域:指針等價,文本等價和內存等價 – JaredPar

+0

-1抱歉,但我有一個指針比較,因爲我想比較指針。這就是問題所在。 – AMCoder

4

1)能夠保證所有的A == B'

不是。請注意,您正在比較地址,他們可能指向不同的位置。大多數智能編譯器會摺疊這個重複的文字常量,因此這些指針可能會相等,但又不會被標準保證。

2)爲什麼不a == c?編譯器不應該看到它們指的是相同的字符串嗎?

您試圖比較指針,它們指向不同的內存位置。即使你在比較這些指針的內容,它們仍然是不相等的(見下一個問題)。

3)在c的末尾是否附加了一個\ 0,即使它已經包含了一個?

是的,有。

+0

我知道我在比較地址,請問這個問題。要清除這個問題 - 相同的字符串文字位於相同的內存中嗎? – AMCoder

+0

我猜'a'和'c'的指針可以相等。一個程序不能在不調用UB的情況下區分它們。 –

+0

@R。馬丁尼費爾南德斯:這是一個好點,我相信你是對的。 –

0

如果你正在做指針比較比!= b,b!= c,並且c!= a。除非編譯器足夠聰明才能注意到你的前兩個字符串是相同的。

如果你做了一個strcmp(str,str),那麼你所有的字符串都會作爲匹配返回。

我不確定編譯器是否會向c添加一個額外的空終止符,但我猜測它會。

3

首先注意,這應該是const char *,因爲這是字符串文字衰減到的。

  1. 兩者都創建用't''e''s''t'用'\ 0'(長度= 5)覆蓋的初始化數組。比較平等只會告訴你他們是否都以相同的指針開始,而不是如果他們有相同的內容(儘管在邏輯上,這兩個想法相互依存)。
  2. A不等於C,因爲相同的規則適用,a ='t''e''s''t''\ 0'和b ='t''e''s''t'' \ 0''\ 0'
  3. 是的,編譯器總是這樣做,你不應該在做這樣的字符串時明確地做。但是,如果您創建了一個數組並手動填充它,則需要確保添加\ 0。

請注意,對於我的#3,const char [] =「Hello World」也會在最後自動獲得\ 0,我正在重新手動填充數組,而不是讓編譯器解決它。

+0

我不認爲'a'和'c'保證不相等。該標準允許實現將文字存儲在重疊存儲中,並且程序無法在不調用UB的情況下區分這些差異。 –

+0

我確實同意你的檢查,這是一個我沒有聽說過的點。我的觀點仍然是,編譯器肯定會在情況2中放置兩個空終止符,儘管這會使操作不平等,即使讀取字符串和檢查它們的指針也是相等的。另外,如果您記錄了爲c創建的字符串的長度,則可以安全地讀取strlen()的過去1,並且不能爲a(除非它們與您所說的位置相同,但是您不會)不能保證)。 –

+0

*即使編譯器將它們存儲在相同的位置*,「a [5]」(它嘗試讀取與c [5]'相同位置的值)會調用未定義的行爲,因爲「a」指向一個大小爲5的數組。沒關係的是恰好有另一個數組放在同一個地方。 –

0

正如其他答案中所說的幾次,你在比較指針。但是,我會補充說strcmp(b,c)應該是真的,因爲它在第一個\0停止檢查。

相關問題