1

私は K&R の本から C を学んでおり、第 5 章では、(配列インデックスを使用する代わりに) ポインターを使用した strcpy() の実装を示しています。次のように述べています。

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

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

どちらも同じことを行い、その!= '\0'部分は必要ありません。しかし、私はその理由を完全には理解していません。'\0'そのヌル文字を指すポインターが逆参照された場合、ゼロに相当しますか?

*編集:'\0'がゼロに等しい場合、これも機能しますか? *

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

5 に答える 5

2

どちらも同じことを行い、その!= '\0'部分は必要ありません。しかし、私はその理由を完全には理解していません。

C では、条件式が期待される場所では、非 0 の数値 (整数と浮動小数点値) と非NULLポインターは真として解釈され、ゼロNULLと偽は偽と見なされるためです。しかし、それはあなたの質問の2番目の部分とはまったく関係ありません.

そのヌル文字を指すポインターが逆参照された場合、「\ 0」はゼロに相当しますか?

どのコンテキストでも、常に,と同等です。0たとえ. void *foo = '\0';_ foo_ NULL_ NULLしかし、積分と積分を比較しているだけなので、ポインタについて尋ねている理由がわかりません(両方charともint整数型です)。

于 2013-10-10T20:15:59.280 に答える
2

はい、'\0'ヌル文字は0です。

条件式を理解するには、次の点を考慮してください。

1:結合代入演算子=は右から左への代入であるため、式

a = b = c;

以下と同等です。

a = (b = c);

と同等の効果で:

b = c;
a = b;

2:ポインター代入式:

*s++ = *t++; 

以下と同等です。

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

3:と式:

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

以下と同等です。

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

四:

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

以下と同等です。

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

[回答] :
2 番目の while ループでは、次のようになります。

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

命令は、アドレス byの値"*s++ = *t++をアドレス by の値にコピーし、その値が while ループのブレーク条件になるため、ループは に等しい値が見つかるまで実行されます。ts\00

したがって、条件式は 両方の run until(*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) 

命令s[i] = t[i] は、最初に の値をコピーt[i]してから、最後に (=0) である while ループのブレーク条件としてs[i]の値を使用します。s[i]\0

于 2013-10-10T20:12:19.993 に答える
1

ascii 48 のように 0 と入力された文字が必要な場合は、当然 '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マッピングの「ブール値」ではなく、コピーの側面に重点を置いていました。

于 2013-10-10T20:17:24.330 に答える