printf("%f\n",x);
x
タイプlong
は ですが、%f
コンバーターは (タイプ の) 浮動小数点値を想定していdouble
ます。通常、浮動小数点値を予期する関数に整数を渡すと、値はサイレントに変換されます。ただし、これは、固定数の引数と、各引数の型を示すプロトタイプを持つ関数にのみ適用されます。などの可変引数関数には適用されません。これはprintf
、コンパイラが値を何に変換するかを知るのに十分な情報を持っていないためです。書式文字列は実行時にのみ分析される可能性があります。
言語仕様では、このプログラムの動作は定義されていません。何でもできます。この場合、おそらく起こっていることx
は、整数レジスタにf
格納され、浮動小数点レジスタに格納されていることです。printf
呼び出しは浮動小数点値を探しているため、コンパイルされたコードは最初の浮動小数点レジスタを調べます。に浮動小数点値を渡した場合printf
、引数はそのレジスタに格納されます。しかし、あなたはそうしなかったので、そのレジスタの値はそこに格納された最後の値でした: によって読み取られた値scanf
です。
優れたコンパイラは、何か間違ったことをしていると警告します。たとえば、コードをコンパイルすると、次のようになりますgcc -O -Wall
。
a.c:2: warning: return type of 'main' is not 'int'
a.c: In function 'main':
a.c:7: warning: format '%d' expects type 'int', but argument 2 has type 'double'
a.c:9: warning: format '%f' expects type 'double', but argument 2 has type 'long int'
a.c:12: warning: format '%f' expects type 'double', but argument 2 has type 'long int'
a.c:15: warning: format '%f' expects type 'double', but argument 2 has type 'long int'
a.c:18: warning: format '%f' expects type 'double', but argument 2 has type 'long int'
このような警告を出力するようにコンパイラを構成し、注意を払うことをお勧めします。
プログラムを動作させるには、浮動小数点値が期待される場所に浮動小数点値を渡すかprintf
、整数値を期待するように指示します。また
printf("%f", (double)x);
また
printf("%ld", x);