4
printf("line 5: %f\n",98);  //output is 0.000000
printf("line 6: %f\n",98.98); //output is 98.980000  
printf("line 5: %f\n",98);//though same as first printf statement but output is 98.979980

最初と最後のprintfステートメントはまったく同じですが、それらの出力は異なります。なんで?

float が予期されているときに int が printf に渡されているため、奇妙な動作をするのはそのためです。しかし、私のポイントは、最後の印刷ステートメントで、ガベージ値または0を印刷する代わりに、2番目のprintfステートメントの値を使用していて、それが印刷される理由です。

4

5 に答える 5

5

他の人がすでに言ったように、予期しないときにintto を渡すと、未定義の動作が発生し、何かが起こる可能性があります。プログラムが乱数ではなく 3 行目に出力する理由に興味があるかもしれません。printfdouble98.979980

引数はスタックで渡されprintfます。行 2 が渡さ98.98れると、番号の最下位部分が最初printfにスタックにプッシュされます。

そのprintf後戻り、3 行目で再度呼び出さ98れ、スタックにプッシュされます。あなたのアーキテクチャでは、intタイプは 32 ビットのようです。型のサイズの半分であるため、以前にスタックにあっdoubleた下半分のみが上書きされます。98.9898.98 の上半分はまだスタックにあります。

への 3 番目の呼び出しは、スタックからprintfa を読み取ります。double読み取るものの最上位半分は、98.98以前にスタックにあった から取得され、下位半分は のバイナリ表現から取得され98ます。これが、結果が に非常に近い理由98.98です。98 は非常に小さい数値であるため、最上位ビットは 0 になり、最下位半分98.98をほとんどゼロに設定すると、より小さな数値が得られます。

行 3 で、より多くのビットが 1 に設定された数値を使用した場合、より大きな結果が得られます98.98。たとえば、-1 のバイナリ表現では、すべてのビットが 1 に設定されており、次のようになります。

printf("line 2: %f\n", 98.98); # 98.98
printf("line 3: %f\n", -1);    # 98.980042

コンパイラが 64 ビットの int を使用した場合、またはdouble最上位部分を最初に s に渡した場合、またはスタックの代わりにレジスタを使用してパラメーターを渡した場合、非常に異なる結果が得られます。

于 2013-07-07T17:49:43.480 に答える
4

プログラムが未定義の動作 を呼び出すためです。98タイプは ですint%ffloat(またはdouble、デフォルトのプロモーション ルールにより ) が必要です。

したがって、printf()変換指定子の型と実際の型が一致しない場合に UB があるため、それが行うことについて合理的な説明はありません。

于 2013-07-07T17:26:13.583 に答える
2

これは%f、double パラメーターが必要なためです。を与えることintは未定義の動作です。

ISO/IEC 9899:1999 §7.19.6.1、9 :

対応する変換仕様に対して正しい型でない引数がある場合、動作は未定義です。

未定義の動作とは、動作が予測できないコンピューター コードを指します。

少なくとも gcc では、警告が有効になっている場合、それに応じて警告が表示されます。

警告: フォーマット '%f' はタイプ 'double' を想定していますが、引数 2 のタイプは 'int' です

于 2013-07-07T17:26:35.443 に答える