8

もっと簡単にできるはずなので、おそらく私はこれを考えすぎているのでしょう。fgetc() によって返されるような int 型の値を取得し、それがファイル終了コードでない場合は char バッファーに記録したいと考えています。例えば:

char buf;
int c = fgetc(stdin);

if (c < 0) {
    /* handle end-of-file */
} else {
    buf = (char) c;  /* not quite right */
}

ただし、プラットフォームがデフォルトの char に署名している場合、fgetc() によって返される値は char の範囲外である可能性があります。その場合、(signed) char にキャストまたは代入すると、実装定義の動作が生成されます (そうですか?)。ただし、確かに、この例とまったく同じことを行うコードがたくさんあります。それはすべて実装定義の動作に依存しているか、および/または7ビットデータを想定していますか?

私のコードの動作がCによって定義されていることを確認したい場合は、次のようにする必要があります。

buf = (char) ((c > CHAR_MAX) ? (c - (UCHAR_MAX + 1)) : c);

デフォルトの文字が符号付きか符号なしかに関係なく、文字のサイズに関係なく、定義された正しい動作が生成されると思います。そうですか?そして、移植性を確保するためにそれを行う必要は本当にありますか?

4

3 に答える 3

3

実際には、それは単純です - への明らかなキャストはchar常に機能します。
しかし、あなたは移植性について尋ねています...

実際のポータブル ソリューションがどのように機能するかわかりません。
これは、 の保証範囲charが -127 ~ 127 で、255 の異なる値しかないためです。では、情報を失うことなくfgetc( を除くEOF)の 256 個の可能な戻り値を に変換するにはどうすればよいでしょうか?char

私が考えることができる最善の方法は、を使用unsigned charして回避することcharです。

于 2013-10-08T15:17:22.377 に答える
3

fgetc()リターンunsigned charとEOF。EOF は常に < 0 です。システムcharsignedまたはの場合、unsigned違いはありません。

C11dr 7.21.7.1 2

stream が指す入力ストリームのファイル終了標識が設定されておらず、次の文字が存在する場合、fgetc 関数はその文字を int に変換されたunsigned charとして取得し、ストリームに関連するファイル位置標識を進めます。 (定義されている場合)。

私が懸念しているのは、 が 2 の補数に依存しているように見え、 と の範囲が同じくらい広いことを意味することunsigned charですchar。これらの仮定はどちらも、今日ではほぼ常に正しいと言えます。

buf = (char) ((c > CHAR_MAX) ? (c - (UCHAR_MAX + 1)) : c);

[OP コメントごとに編集]がから までの範囲でスタッフィング可能な以外の文字を返さない
と仮定すると、より移植性が高くなり、 に置き換えられます。がいつ範囲内にあるかはわかりません。fgetc()CHAR_MINCHAR_MAX(c - (UCHAR_MAX + 1))(c - CHAR_MAX + CHAR_MIN)(c - (UCHAR_MAX + 1))c is CHAR_MAX + 1

-127 から +127 の範囲と 0 から 255 の範囲を持つシステム存在する可能があります(5.2.4.2.1)。に変換し、その値をユーザーに返す前に。OTOH、256 の異なる文字が返された場合、数式に関係なく、狭い範囲への変換は移植できません。signed charunsigned charfgetc()unsigned char signed charunsigned charfgetc()signed char

于 2013-10-08T14:38:01.257 に答える