次のコードが壊れていることはわかっています--getchar()
返さint
ないchar
--
良い!
char single_byte = getchar();
これは複数の方法で問題があります。
と仮定CHAR_BIT == 8
しEOF == -1
ます。(EOF
が負であり、型がint
;-1
であることがわかっています。これは典型的な値です。実際、他の値を持つことは聞いたことがありません。)
プレーンchar
は、署名付きまたは署名なしのいずれかです。
符号なしの場合、 のsingle_byte
値は、読み取られたばかりの文字の値 ( として表され、unsigned char
単純にプレーンに変換されますchar
)、または に変換EOF
した結果のいずれかになりchar
ます。通常EOF
は -1 で、変換の結果は、または 255 になります。と実際の入力値 255CHAR_MAX
を区別することはできません。また、すべてのバイト値が等しい確率で返されるため (そして枯渇することはありません) 。 、遅かれ早かれバイトが表示されます。EOF
/dev/urandom
0xff
しかし、それはあなたの入力ループを終了しません。あなたの比較(single_byte == EOF)
は決して真実ではありません。このシナリオでsingle_byte
は は符号なしタイプであるため、 と等しくなることはありませんEOF
。のような無制限のデバイスからではなく、有限のファイルから読み取る場合でも、無限ループが発生します/dev/urandom
。( と書くこともでき(single_byte == (char)EOF)
ましたが、もちろんそれでは根本的な問題は解決しません。)
char
ループが終了するため、プレーンがシステムで署名されていると結論付けることができます。
プレーンchar
が署名されている場合、事態はもう少し複雑になります。0..127 の範囲の文字を読み取った場合、その値は に格納されsingle_byte
ます。128..255 の範囲の文字を読み取ると、int
値は;に変換されます。char
はchar
符号付きで、値が範囲外であるため、変換の結果は実装定義です。ほとんどの実装では、その変換は 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ビット値を取った結果である可能性がありますchar
int
int
unsigned int
single_byte
-1
EOF
printf
"%x"
unsigned int
0xffffffff
int
-1
そして、それが本当にunsigned int
.
getchar()
の結果をオブジェクトに格納することは、 に格納int
したときに何が起こるかを分析するよりもはるかに簡単だったことに注意してくださいchar
。