どちらの場合も、コードは整数型からfloat
.double
への変換を試みます。変換は、可変引数関数に渡される値double
であるため発生します。float
の設定を確認しFLT_EVAL_METHOD
、値が 1 または 2 であると思われます (2
少なくとも 1 つのコンパイラを使用した OP レポート)。これにより、コンパイラはfloat
より大きい「範囲と精度に対する演算と定数」を評価できますfloat
。
コンパイラ(float)x
は、直接演算int
に最適化されました。double
これは、実行時のパフォーマンスの向上です。
(float)2147483647
はコンパイル時のキャストであり、パフォーマンスはここでは問題にならないため、コンパイラは正確に最適化されint
てfloat
います。double
[Edit2] C11 仕様が C99 仕様よりも具体的で、「代入とキャストを除く...」が追加されているのは興味深いことです。これは、C99 コンパイラが最初に通過せずint
に直接変換を許可することがあり、C11 が修正されてキャストのスキップが明確に許可されなかったことを意味します。double
float
C11 ではこの動作が正式に除外されているため、最新のコンパイラはこれを行うべきではありませんが、OP のような古いコンパイラはこれを行う必要があります。つまり、C11 標準によるバグです。他の C99 または C89 仕様で別段の記述がない限り、これは許容されるコンパイラの動作のようです。
[編集] @Keith Thompson、@tmyklebu、@Matt McNabb によるコメントをまとめると、コンパイラは、ゼロ以外の であっても、FLT_EVAL_METHOD
を生成することが期待され2147483648.0...
ます。したがって、コンパイラの最適化フラグが正しい動作を明示的に上書きしているか、コンパイラにコーナー バグがあります。
C99dr §5.2.4.2.2 8 浮動オペランドを伴う演算の値、および通常の算術変換の対象となる値、および浮動定数の値は、その範囲と精度が型で必要とされるよりも大きい形式に評価されます。評価形式の使用は、FLT_EVAL_METHODの実装定義の値によって特徴付けられます。
-1 不定;
0 は、すべての演算と定数を型の範囲と精度だけで評価します。
1 型の演算と定数を型float
のdouble
範囲と精度でdouble
評価し、型の範囲と精度でlong double
演算と定数を評価しlong double
ます`;
2 すべての演算と定数を型の範囲と精度で評価しますlong double
。
C11dr §5.2.4.2.2 9 代入とキャスト (すべての余分な範囲と精度を削除する) を除き、浮動オペランドを持つ演算子によって生成された値と、通常の算術変換および浮動定数の対象となる値は、その範囲の形式に評価されます。精度は、型で必要とされるよりも大きい場合があります。評価フォーマットの使用は、FLT_EVAL_METHODの実装定義の値によって特徴付けられます。
-1 (C99 と同じ)
0 (C99 と同じ)
1 (C99 と同じ)
2 (C99と同じ)