アプリ版:「スタンプのみでお礼する」機能のリリースについて

C言語初心者です。
unsigned int型に関する質問です。
---------------------------------
#include <stdio.h>

int main(void) {
unsigned int in1 = 10;
unsigned int in2 = -10;
unsigned char ch1 = 10;
unsigned char ch2 = -10;

printf("in1 = %d\n", i);
printf("in2 = %d\n", i);
printf("ch1 = %d\n", ch1);
printf("ch2 = %d\n", ch2);

return 0;
}
---------------------------------
上記のプログラムを作成して実行すると、結果は以下の通りです。

[実行結果]
in1 = 10;
in2 = -10;
ch1 = 10;
ch2 = 246;

変数in2の値を表示した結果に関してですが、
unsigned int型にも関わらず負の値「-10」が表示されるのは
何故でしょうか?

A 回答 (6件)

他の回答者さんの通りですが、補足したいと思います。



C の printf() 関数は、他の関数(正確には引数の個数が決まっている普通の関数)とはすこし勝手がちがいます。

どう違うかというと、printf() で format に続く引数の型がどうなっているかは、printf() が呼び出されて printf() が fomrat を調べて始めて分かります。ここで「分かる」と言いましたが、どういう型なのかは format に "%d" だと int 型の引数がある、と思い込んでいるだけなので、そうでない型が来ていても、そのまま何も考えずに表示しようとします。

gcc でコンパイルすると型が違った場合、コンパイル時にチェックして警告が出たりします(ただし -Wall などの警告オプションを付けた時)。

ですから、極端な話、

char *p;
printf( "%d\n", p );

とやってもちゃんと動作しますが、出力された数値はとんでもない数字になります。つまりポインタを符号付き整数だと思い込んで出力しているのです。

ということで、質問者さんの場合では、printf() の format に "%u" としてして「ここの引数は符号無し整数だよ」と教える必要があります。
    • good
    • 0
この回答へのお礼

非常にわかりやすいご回答ありがとうございました。
勉強になりました。

お礼日時:2008/03/23 21:24

printfでformatに%dを指定して、符号ありの整数として出力しているから。


符号なし整数で表示する場合は%uです。

32bitの変数で-10は0xfffffff6です。
(意味が解からなければ補数とかで調べて下さい。)
だからin2には0xfffffff6っていう数値が入ってます。
これを符号ありの整数として扱うと-10です。
符号無しの整数として扱えば4294967286です。

試しに
unsigned int in2 = 4294967286;
や、
unsigned int in2 = 0xfffffff6;
に書き換えて試してみてください。
同じ結果が得られることでしょう。

unsignedと宣言している以上、-10を代入するなんてことは普通はやっちゃダメです。
    • good
    • 0
この回答へのお礼

基本的な間違いですね。失礼しました。
今後は気をつけます。

お礼日時:2008/03/23 21:23

#4です。

訂正。
汎整数拡張では、負数の変換についても正式に定義されているんですね。
ということは、
>unsigned int in1 = 10;
in1=10
>unsigned int in2 = -10;
in2= -10 + ( UINT_MAX + 1 ) = -10 + (4294967295+1)=4294967286
>unsigned char ch1 = 10;
ch1=10
>unsigned char ch2 = -10;
ch2= -10 + ( UCHAR_MAX +1 )= -10 + ( 255 + 1 ) = 246
であって、

>printf("in1 = %d\n", i);
unsigned intからintへの変換で、intで表現可能なので、10と表示
>printf("in2 = %d\n", i);
unsigned intからintへの変換で、intで表現不可能なので、処理系定義
>printf("ch1 = %d\n", ch1);
unsigned charを引数に渡すときにintに変換、intで表現可能なので、10のまま。
intで表示しようとするので、10と表示
>printf("ch2 = %d\n", ch2);
unsigned charを引数に渡すときにintに変換、intで表現可能なので、246のまま。
intで表示しようとするので、246と表示
ということですね。
ということで、
>printf("in2 = %d\n", i);
が間違い(処理系依存)ということですか。

#intが32bit,char が8bitで考えています。
    • good
    • 0

>変数in2の値を表示した結果に関してですが、



> unsigned int in2 = -10;
unsignedに負の値を代入しているし、
> printf("in2 = %d\n", i);
unsigned intの値を%dで表示しようとしている。
つまり間違ったプログラムだから。「-10」が表示されたのはたまたまに過ぎません。
ちなみに、この中で正しいのはch1だけのはず。
    • good
    • 0

> unsigned int型にも関わらず負の値「-10」が表示されるのは


> 何故でしょうか?

"%d" は signed int として扱うからです。
"%u" とすれば unsigned int として扱われます。

コード
printf("in1 = %u\n", in1);
printf("in2 = %u\n", in2);
printf("ch1 = %u\n", ch1);
printf("ch2 = %u\n", ch2);

結果
in1 = 10
in2 = 4294967286
ch1 = 10
ch2 = 246

printf のフォーマットについて調べてみてはいかがでしょうか?
    • good
    • 0

printfの変換指定子"%d"で符号なしから符号ありへ型が変換されたためでしょう


変数の型と表示の型を合わせるなら
printf("in1 = %d\n", in1);
printf("in2 = %u\n", in2);
printf("ch1 = %hhd\n", ch1);
printf("ch2 = %hhu\n", ch2);
としましょう
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!