書式指定子として %d を指定して printf を使用し、引数として 2.345 などの浮動小数点数を指定すると、1546188227 が出力されます。これは、単一小数点浮動小数点精度書式から単純な 10 進書式への変換が原因である可能性があることを理解しています。しかし、フォーマット指定子として %d を使用して 2.000 を出力すると、なぜ 0 しか出力されないのでしょうか? 助けてください。
6 に答える
書式指定子は、型(および互換性のある型)%d
の値でのみ使用できます。またはその他の型int
を使用しようとする%d
と、未定義の動作が発生します。float
ここで真に当てはまる説明はこれだけです。言語の観点から見ると、表示される出力は基本的にランダムです。また、出力がまったく得られる保証もありません。
実際の動作はさまざまな実装の詳細に大きく依存するため、表示される出力の特定の理由を調査することに引き続き関心がある場合 (意味はほとんどありません)、プラットフォーム固有の調査を実行する必要があります。また、投稿でプラットフォームについて言及していません。
float
いずれにせよ、補足として、値を可変引数として可変引数関数に渡すことはできないことに注意してください。float
このような場合の値は常に に変換されdouble
、 として渡されdouble
ます。したがって、あなたの場合、double
印刷しようとしているのは値です。ただし、動作はまだ未定義です。
ここに、ISO / IEC 9899:1999標準$7.19.6が述べているものがあります。
If a conversion specification is invalid, the behavior is undefined.239)
If any argument is not the correct type for the corresponding conversion
specification, the behavior is undefined.
ここに行き、 を入力2.345
し、「丸め」をクリックします。64 ビットの 16 進数値を確認します: 4002C28F5C28F5C3
. であることに注意し1546188227
て0x5c28f5c3
ください。
2.00 に対して繰り返します。64 ビットの 16 進数値が4000000000000000
PSfloat引数を与えると言うとき、明らかに意味するのは、double引数を与えるということです。
整数値を出力しようとしている場合は、呼び出しで float を int にキャストします。
printf("ints: %d %d", (int) 2.345, (int) 2.000);
それ以外の場合は、浮動小数点形式の識別子を使用します。
printf("floats: %f %f", 2.345, 2.000);
対応する引数に間違った書式指定子を指定して printf を使用すると、結果は未定義の動作になります。それは何でもかまいませんし、実装ごとに異なる場合があります。指定された形式を正しく使用した場合にのみ、動作が定義されます。
最初のちょっとしたヒント: リテラル 2.345 は実際には float ではなく double 型であり、さらに、リテラル 2.345f などの float でさえ、変数を受け取る関数の引数として使用すると double に変換されます。 printfなどの引数の。
しかし、ここでは (通常) 64 ビットの double 値が printf に送信され、(通常) 32 ビットが整数値として解釈されます。したがって、それらのビットがゼロだったのはたまたまです。
標準によれば、これは未定義の動作と呼ばれるものです。つまり、コンパイラは何でも実行できます。