• ベストアンサー

-1 はいくつ

下記 C プログラムを実行しました。 printf ("char:%x\n",(char)-1); printf ("unsigned char:%x\n",(unsigned char)-1); 前者では -1 が ffff、後者では -1 が ff と出力されました。どうしてこうなるのでしょう。私の C コンパイラのムシでしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
  • MASATO3
  • ベストアンサー率60% (27/45)
回答No.4

●ルール1 C言語では、char型からint型に変換するとき、符号拡張が行われます。 符号拡張というのは、ビット幅が広い型に変換するとき、 変換前の値が負の場合、広がった部分のビットを"1"にし、 変換前の値が正の場合、広がった部分のビットを"0"にする、という処理です。 (例) char型が8bitでint型が16bitだった場合、 char型で -1(0xff) →変換→ int型で -1(0xffff) char型で -128(0x80) →変換→ int型で-128(0xff80) char型で 127(0x7f) →変換→ int型で 127(0x007f) ●ルール2 unsigned char型からint型に変換するときは、符号拡張ではなく ゼロ拡張が行われます。 ゼロ拡張というのは、広がった部分のビットを"0"にする処理です。 (例) unsigned char型が8bitでint型が16bitだった場合、 unsigned char型で 255(0xff) →変換→ int型で 255(0x00ff) unsigned char型で 128(0x80) →変換→ int型で 128(0x0080) unsigned char型で 127(0x7f) →変換→ int型で 127(0x007f) ●ルール3 でもって最後に、printfですが、 これは、可変長引数を使った関数です。 こうした関数の可変長引数部に値を渡す前に、intよりも小さい型はintに変換されます。 そうした結果、 printf ("char:%x\n",(char)-1); というprintf呼び出しでは、ルール3によりprintfに値が渡る前に、 ルール1が適用されて、0xffffに変換されます。 この値がprintfに渡され、printfはそのままffffと表示しているわけです。 なお、int型が32bitの場合はffffffffになります。 ffffになったのはtanukさんご利用のコンパイラではint型が16bitだからでしょう。 printf ("unsigned char:%x\n",(unsigned char)-1); というprintf呼び出しでは、ルール3によりprintfに値が渡る前に、 ルール2が適用されて、0x00ffに表示されます。 yasuchさんが言われている通り、 "%x" では 0x00ff の先頭の 00 は省略される為表示されません。 そのため、ffと表示されるわけです。

tanuk
質問者

お礼

回答ありがとうございます。 printf の引数で int よりも小さい型は int に変換されるというルールがあったのですね。よく分かりました。

その他の回答 (3)

  • yasuch
  • ベストアンサー率41% (27/65)
回答No.3

(char)-1 は -1 (unsigned char)-1 は No.1 さんが書かれているとおり 255 とコンパイラが認識しています。 それぞれを、"%x" で表示する為に整数型(INT)にキャストすると -1 は INT型で -1(0xffff) 255 は INT型で 255(0x00ff) "%x" では 0x00ff の先頭の 00 は省略される為表示されません。

tanuk
質問者

お礼

回答ありがとうございます。 > (char)-1 は -1 この -1 は char 型ですからこれも内部表現は 0xff、つまり 255 と思えばいいのですね。 > それぞれを、"%x" で表示する為に整数型(INT)にキャストすると "%x" で表示する際に整数型(INT)にキャストされるという C の規則があったわけですか。それなら理解できます。ありがとうございました。

  • ysk6406
  • ベストアンサー率40% (237/589)
回答No.2

> なぜ char の方は 16bit の ffff が出力されるのかがよく分からないのですが。 この種の問題は、コンパイラの実装によって結果が異なります。 あなたのコンパイラでは、おそらく int 型が2バイトであり、printf での出力の際に値が int 型に変換されているのでしょう。 従って、環境が変われば値も変わります。 私の環境では、あるコンパイラでは ffffffff、別のコンパイラでは ff と出力されます。

tanuk
質問者

お礼

回答ありがとうございます。 > おそらく int 型が2バイトであり、printf での出力の際に値が int 型に変換されているのでしょう。 確かに int 型は 2 バイトです。わざわざ char でキャストしているのに、printf のときまた int でキャストされるわけですか。なかなか複雑ですね。 ご自身の環境まで調べていただきありがとうございました。

  • katouka09
  • ベストアンサー率50% (130/256)
回答No.1

あなたの勘違いです。 0xffを10進数で表示させてみればわかります。 char型とunsigned char型では扱える範囲が異なります。 unsigned char型の場合は、0~255なので負の数字は扱えません。したがって-1を代入すると扱える範囲の最大数である255となり16進数で0xffとなるのです。 入門書等を読み直しましょう。

tanuk
質問者

お礼

unsigned char の方は常識的な ff が出力されるのに、なぜ char の方は 16bit の ffff が出力されるのかがよく分からないのですが。

関連するQ&A