2013-10-10 93 views
1

我從K & R書中學習C,並在第5章中介紹了帶有指針的strcpy()的實現(而不是使用數組索引)。它說:當使用指針時,爲什麼' 0'等於0?

while ((*s++ = *t++) != '\0') 

while (*s++ = *t++) 

都做同樣的事情,那!= '\0'部分是沒有必要的。但我不完全明白爲什麼。 當指向該空字符的指針被解除引用或其他東西時等於零?

* 編輯:所以如果'\0'等於零,那麼這也會工作嗎? *

while (s[i] = t[i]) i++; 
+3

無論是使用指針還是不使用,''\ 0''都等同於'0'。例如。 ''\ 0'== 0'。閱讀整數促銷章節。 –

+3

@AntonTykhyy,沒有整數推廣發生。 ''0'和'0'都是'int'。好吧,無論如何,在C中。 –

+1

爲什麼這個問題標記爲C++,如果你問C? –

回答

2

兩者都做同樣的事情,並且!= '\0'部分是沒有必要的。但我不完全明白爲什麼。

因爲在C中,在條件表達式預計的地方,非0的數字(整數和浮點值)和非NULL指針被解釋爲真,和零NULL被認爲是錯誤的。但是這與你的問題的第二部分沒有任何關係。

是「\ 0」等於零時,指向那個空字符指針被廢棄的東西?

這是總是相當於0,在任何情況下。即使你做void *foo = '\0';,它也會將foo設置爲NULL,因爲整數立即數0對於指針來說是一個合適的初始值設定項,並且它被轉換爲NULL。但我不明白你爲什麼要問關於指針的問題,因爲你只是比較積分和積分(charint都是整數類型)。

+0

爲什麼downvote?至少解釋一下吧! – 2013-10-10 21:22:11

+0

再一次,你爲什麼低估了thia? – 2013-10-11 04:51:28

+0

是的,我知道你已經暗示了它,我只是認爲它已經足夠明確地被陳述了(並且爲了記錄,我沒有被低估)。 – bitmask

2

是,'\0' NUL char是0

要了解的條件表達式考慮我的以下幾點:

一:由於關聯賦值運算符=是從右到左,因此表達

a = b = c; 

是等價於:

a = (b = c); 

等效於:

b = c; 
a = b; 

二:指針賦值表達式:

*s++ = *t++; 

是等同於:

*s = *t; 
t++; 
s++; 

三:和表達式:

con = *s++ = *t++; 

是等同於:

*s = *t; 
con = *s; 
t++; 
s++; 

四:

(*s++ = *t++) != '\0' 

是等同於:

*s = *t; 
*s != '\0'; 
t++; 
s++; 

[答案]
所以在第二while循環:

通過 t地址
while (*s++ = *t++); 
//  ^ ^
//  |  | 
//  assign then increments 
// then break condition = *s (updated value at *s that is \0 at the end) 

指令"*s++ = *t++副本值由s地址的值,然後該值變成while循環間隔條件,那麼循環運行,直到發現\0等於0

因此,條件表達式(*s++ = *t++)相當於(*s++ = *t++) != '\0'都運行到*s != 0

最後同時:

while (s[i] = t[i]) i++; 
//  ^ ^ ^
//  |  |  increments 
// assign then increments 
// then break condition = s[i] (s[i] is \0 at the end) 

指令的t[i]s[i]s[i] = t[i]第一副本值然後s[i]值使用作爲打破的while循環即\0(= 0)在結束條件。

+2

沒有涉及ASCII。 '\ 0'只是'0'。 –

+0

@CarlNorum你的意思是'\ 0'不是char? –

+0

確定它是一個字符常量,但這與ASCII沒有任何關係。 –

1

如果你想輸入的字符爲0,如在ASCII 48中,你自然會使用'0'。

由於'0'已被採用,爲了指定「特殊」NUL字符,需要不同的序列。正如很多人所理解的,NUL等於0的二進制值,他們選擇了'\ 0'。

所以

'\0' == 0 

返回true,但

'0' == 48 // ASCII only, EBCDIC programmers need to lookup their own values ;) 

返回true太

是的,有很多方法可以讓寫strcpy()內部。然而,指針和數組在代表性上是等價的,有時(即使沒有必要),明確的比較器可以防止人們關注示例的錯誤元素。因此,我相信並不是強迫讀者理解循環會在遇到NUL字符時終止,而是寫在一個使得終止顯而易見的條款中(任何體面的編譯器可能會優先考慮)。畢竟,他們真的專注於複製方面,而不是「布爾」映射到int

+0

''\ 0''不是一個特殊的轉義序列。一個字面值爲'0'的八進制字符常量 –

+1

「''0'== 60'也返回true」 - 不在我的EBCDIC主機上。 – 2013-10-10 20:18:21

+0

@ H2CO3 Touche,並且都是真的。 '0'!= ASCII_NUL',這是要做的點 –

0

反斜槓表示會有一些特殊情況字符串例如:

`\r` means carriage return and it is equal 13 
`\n` means line feed and it is equal 10 
there are more of these and in your mentioned case: 
`\0` means null and is equal 0 

那是怎樣c作品。

+0

'\ n'表示換行 - 爲真。當使用幾乎通用的ASCII字符編碼時,它的值等於10。但是C沒有將'\ n'定義爲10,也不需要ASCII。類似於\ r。 – chux

0

'\0'0意思是一樣的東西,所以使用前者只是語法糖。

關鍵是讓代碼更具可讀性,因爲我們在這裏處理字符串,所以使用數字零的字符符號(用於終止C字符串)更加一致。

如果與數字打交道,最好風格來使用0,如果你對付的人物,'\0'是更好的,如果你處理的指針,NULL是最好的。所有3個符號表示相同,只是爲了清楚。