2013-04-16 8 views
5

GCC 4.8.0が32ビットで/でコンパイルされています。キャスト動作が一致しない可能性があります

私は例との動作が混乱することを見つける:

int16_t s16 = 0; 
double dbl = 0.0; 

s16 = (int16_t)((double)32767.0); // 1: s16 = 32767 
s16 = (int16_t)((double)32768.0); // 2: s16 = 32767 
s16 = (int16_t)((double)-32768.0); // 3: s16 = -32768 
s16 = (int16_t)((double)-32769.0); // 4: s16 = -32768 

dbl = 32767.0; 
s16 = (int16_t)dbl; // 5: s16 = 32767 
dbl = 32768.0; 
s16 = (int16_t)dbl; // 6: s16 = -32768 
dbl = -32768.0; 
s16 = (int16_t)dbl; // 7: s16 = -32768 
dbl = -32769.0; 
s16 = (int16_t)dbl; // 8: s16 = -32768 

私はそれが定義された実装の実現が、一貫性はまだいいだろう。誰でも何が起こっているのか説明できますか?

+2

'32767.0'、' 32768.0'、 '-32768.0'を' double'にキャストする必要はなく、すでに 'double'型です。 – ouah

+0

@ouahはい、私は知っています。私はその行動を強調するためにそうしました。 – Ioan

答えて

3

挙動は実装定義されていない、それは6.3.1.4(1)あたり、未定義です:

不可欠な部分の値が整数型で表現できない場合、動作は未定義です。整数型の値が符号無し型に変換されたときに剰余演算が行わ61)

61)実浮動型の値が符号無し型に変換されたときに実行される必要はありません。したがって、 のポータブル実浮動値の範囲は(−1, Utype_MAX+1)です。

この段落はC99で同じですが、脚注の番号(50)は異なっています。未定義の動作について

、コンパイル時に評価式の挙動は、シフト距離は次のように与えられた場合

​​

はしばしば0に評価され、例えば、ランタイムevaluedとは異なることは珍しくありませんランタイム値の場合は1に設定されます。

同じコードのさまざまな動作につながる推論は、私が収集した限り、未定義の動作はコンパイラが何かを生成するためのライセンスであるため、最も単純で速いコンパイル時の最もシンプルな/最速のものは、実行時の最もシンプルで速いものとは異なる場合があります。

+0

私はC99規格を使用していても問題ありませんか?他の関連する質問では、(一体型の間での)キャスト動作は実装定義であることが示されています。また、私は署名付きの型を使用しています。 – Ioan

+0

いいえ、C99は同じ処方でありました。積分型間の変換は、その振る舞いが実装定義である場合にのみ行われます。(脚注は、ターゲットが符号なしであるときに動作が完全に定義されている、整数型間の変換とは異なり、符号なしのターゲット型に対しても動作が未定義であることを強調しています)。 –

+0

未定義は無回答を意味しますが、一貫しているか、おそらく何らかの理由でヒントがあるかもしれません... – Ioan

0

すでに定義されているように、「定義されていない」は「実装が定義されている」という意味ではありません。

値が制限を超えてしまう可能性がある場合は、変換前の範囲を確認する必要があります。 または、いくつかのライブラリを使用することができます。 itrunc(double)のようなブースト数学関数では、範囲外のときにboost :: math :: rounding_errorを得るべきです(unfortunatelly私はあなたがあなたのint16_tで動作させることができるかどうかわかりません)。挙動が異なっていてもよい理由理由について

http://www.boost.org/doc/libs/1_53_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/rounding/trunc.html

:たぶん実装コピー値を表すビット、それは範囲外であり、それはに設定されたままの符号ビットを気にせずに終了することを認識ランダム値

関連する問題