2

次のコードが壊れていることはわかっています--getchar()返さintないchar--

#include <stdio.h>
int
main(int argc, char* argv[])
{
  char single_byte = getchar();

  while (single_byte != EOF) {
    single_byte = getchar();
    printf("getchar() != EOF is %d.\n", single_byte != EOF);
    if (single_byte == EOF)
      printf("EOF is implemented in terms of 0x%x.\n", single_byte);
  }

  return 0;
}

それの典型的な出力(/dev/urandomたとえば、入力ストリームとして使用)は、次ではなくEOF is implemented in terms of 0xff、最後にあったと思いますが

$ ./silly < /dev/urandom
getchar() != EOF is 1.
getchar() != EOF is 1.
// ...
getchar() != EOF is 0
EOF is implemented in terms of 0xffffffff.

さらに、0xffffffff1バイトに格納することはできません...

前もって感謝します

4

5 に答える 5

1

次のコードが壊れていることはわかっています--getchar()返さintないchar--

良い!

char single_byte = getchar();

これは複数の方法で問題があります。

と仮定CHAR_BIT == 8EOF == -1ます。(EOFが負であり、型がint;-1であることがわかっています。これは典型的な値です。実際、他の値を持つことは聞いたことがありません。)

プレーンcharは、署名付きまたは署名なしのいずれかです。

符号なしの場合、 のsingle_byte値は、読み取られたばかりの文字の値 ( として表され、unsigned char単純にプレーンに変換されますchar)、または に変換EOFした結果のいずれかになりcharます。通常EOFは -1 で、変換の結果は、または 255 になります。と実際の入力値 255CHAR_MAXを区別することはできません。また、すべてのバイト値が等しい確率で返されるため (そして枯渇することはありません) 。 、遅かれ早かれバイトが表示されます。EOF/dev/urandom0xff

しかし、それはあなたの入力ループを終了しません。あなたの比較(single_byte == EOF)は決して真実ではありません。このシナリオでsingle_byteは は符号なしタイプであるため、 と等しくなることはありませんEOF。のような無制限のデバイスからではなく、有限のファイルから読み取る場合でも、無限ループが発生します/dev/urandom。( と書くこともでき(single_byte == (char)EOF)ましたが、もちろんそれでは根本的な問題は解決しません。)

charループが終了するため、プレーンがシステムで署名されていると結論付けることができます。

プレーンcharが署名されている場合、事態はもう少し複雑になります。0..127 の範囲の文字を読み取った場合、その値は に格納されsingle_byteます。128..255 の範囲の文字を読み取ると、int値は;に変換されます。charchar符号付きで、値が範囲外であるため、変換の結果は実装定義です。ほとんどの実装では、その変換は 128 を -128 に、129 を -127 に、... 255 を -1 にマップします。getchar()(通常) -1 を返す場合EOF、変換は明確に定義されており、-1 が返されます。EOF繰り返しますが、 と 値を持つ入力文字を区別することはできません-1

(実際には、C99 の時点で、変換によって実装定義のシグナルが発生することもあります。幸い、私の知る限り、実際にそれを行う実装はありません。)

if (single_byte == EOF)
    printf("EOF is implemented in terms of 0x%x.\n", single_byte);

繰り返しますが、この条件は、getchar()実際に返さEOFれた場合、または value を持つ文字を読み取った場合に true になります0xff%x形式には type の引数が必要ですunsigned int。はほぼ確実に に昇格するsingle_byteタイプです。値が両方のタイプの表現可能な範囲内にある場合、値をフォーマットで出力できるようになりました。しかし、の値は( と等しいと比較しただけです) であるため、その範囲にはありません。の形式では、引数が型であると想定します(これは変換ではありません)。そして、の32ビット値を取った結果である可能性がありますcharintintunsigned intsingle_byte-1EOFprintf"%x"unsigned int0xffffffffint-1そして、それが本当にunsigned int.

getchar()の結果をオブジェクトに格納することは、 に格納intしたときに何が起こるかを分析するよりもはるかに簡単だったことに注意してくださいchar

于 2013-09-26T15:00:32.480 に答える
0

(char) -1との間の混同のよう(int) -1です。

getchar()257 の異なる値のうち 1 つで を返しintます: 0 から 255 および EOF。EOF が 0 未満です (C11 7.21.1)。

通常、 EOF の値は -1 であり、あなたの場合はそうです。以下ではそれを仮定してみましょう。

からデータを読み取る/dev/urandomと、値 255 が読み取られることがあります。これはEOFではありません。

OP が を実行すると、 (EOF) が読み取られた場合と読み取られた場合の同じ値をchar single_byte = getchar()取りsingle_byteます。 (char) -1(int) -1(int) 255

次に を比較するときsingle_byte != EOF、結果がであっても、 の元の戻り値が -1 だったのか 255 だったfalseのかわかりません。getchar()

別のものをお勧めしますprintf()

printf("single_byte==EOF, so (int) 255 or EOF was read: 0x%hhx\n", single_byte);

仮定:
charは 8 ビットです。
EOF は -1 です。

于 2013-09-26T13:53:36.770 に答える