2

Stephen G. Kochan による C プログラミングに関する本 Programming in C を読んでいました。それは次のように述べています:

「標準文字の一部ではない文字値が使用されている場合、整数に変換するときにその符号が拡張される可能性があります」

そして、それは述べています

「C言語では、文字変数を符号なしで宣言できるため、この潜在的な問題を回避できます」

char から int への変換中に符号を拡張すると、どのような問題が発生する可能性があるかを誰かが説明できますか? そして、なぜこれが問題なのですか?そして、char から変換された負の整数の何が問題なのですか?

ありがとうございました

4

2 に答える 2

5

<ctype.h> から無害に見える関数を取得するとしますisupper()

定義されていint isupper(int c);ます。したがって、int を取り、int を返します。

ここで、あなたがあまり注意深いプログラマーではなく、この関数に char を渡すだけだとしましょう。「何がうまくいかないんだろう? これは私が知っている最も単純な関数だ!」と思います。

しかし、あなたは間違っているでしょう。どこかで、このひどい間違いのために、誰かが彼女の MP3 プレーヤーを無限のクラッシュ ループに陥らせるでしょう。

その理由は次のとおりです。C で最も面倒な型は char です。署名することも、署名しないこともでき、コンパイラを何らかの方法で強制することもできます (ただし、別のワームを開くこともできます)。さらに最悪なのは、標準 C ライブラリがこの型をあらゆる場所で使用しているということです!

したがって、char を使用しますが、それが実際に環境で署名されているという事実を認識していません。世界が ASCII の世界であるかのように使用します。

しかし、世界はそうではありません。そして、その MP3 の幸せな所有者は、名前に文字 ä (「拡張 ASCII コード 132」) が含まれるドイツの有名な曲を聴いています。

この文字をisupper()に渡すと、コンパイラは次のような恐ろしいことをします。整数に変換して渡す. どうすればよいですか? C 標準を確認してみましょう... うーん... 簡単です、値を取得して符号拡張するだけです (char は符号付きなので、わかりませんか?) . さて、この文字の値は -124 なので、-124 の値を持つ int に変換するだけです. これは簡単なことでした. 何が問題なのかわかりません. なぜプログラマーに警告する必要があるのでしょうか? !」

そしてisupper()、132 の代わりに -124 で呼び出されるようになりました。

しかし、それの何が問題なのですか?コンパイラに付属の C ライブラリがisupper()単純な 128 バイト配列を使用して実装することを除いて、何もありません。指定されたインデックスで値を返すだけです。配列は、1 である大文字の ASCII コードを除いて、どこでも 0 で初期化されます。このようなシンプルで洗練された実装...

この関数に負の値を渡すとどうなるでしょうか。まあ、それは許可されていません:

c 引数は int であり、その値は unsigned char として表現できる文字、またはマクロ EOF の値と等しいことをアプリケーションが保証する必要があります。引数が他の値を持つ場合、動作は未定義です。

したがって、未定義の動作。この場合、プロセスに属さないメモリにアクセスしようとし、BAM! プログラムがクラッシュします。

つまり、char は悪であり、適切に使用する方法を本当に理解していない限り、決して使用すべきではありません。

(*) Keith Thompson がコメントで述べたように、使用を避けることはもちろん不可能charです。からstrlen()までcurl_easy_escape()、誰もが を使用しcharます。intただし、特にcharが負の数を保持している可能性がある場合は、への変換に注意する必要があります。<ctype.h> 関数と配列インデックスは、コストのかかる間違いを犯しやすい 2 つの場所です。

于 2012-11-10T01:01:39.660 に答える
1

C では、plain charは符号付きまたは符号なしのいずれかであり、選択は実装に任されています。

C99、6.2.5、7から:

char、signed char、unsigned char の 3 つの型をまとめて文字型と呼びます。実装では、signed char または unsigned char と同じ範囲、表現、および動作を持つように char を定義する必要があります。

そのため、文字が整数に割り当てられると、char の符号ビットが設定されているかどうかが曖昧になります。これは、プレーンなchar が割り当てられた整数の結果の値に影響を与えるためです。

本から引用されたテキストはこれを参照しており、unsigned char明示的に使用するとこの問題を回避できると思います。

于 2012-11-10T00:57:46.527 に答える