2017-01-18 2 views
3
#define SCALE (1 << 31) 

#define fix_Q31_80(x) ((int) ((float)(x)*(float)0x80000000)) 
#define fix_Q31_SC(x) ((int) ((float)(x)*(float)SCALE  )) 

int main() 
{ 
    int fix_80 = fix_Q31_80(0.5f); 
    int fix_sc = fix_Q31_SC(0.5f); 
} 

fix_80fix_scの値が異なるのはなぜですか?定義(1 << 31)または0x80000000を使用していますか?結果が異なる

fix_80 == Hex:0x40000000 
fix_sc == Hex:0xc0000000 
+0

誰が知っていますか? UBはUB、[IBはIB](http://stackoverflow.com/questions/26331035/why-was-1-31-changed-to-be-implementation-defined-in-c14)です。予測可能な結果が必要な場合は実行しないでください。 –

+0

'(1 << 31)!= 0x80000000' – Peter

+6

ビットシフト時に符号付き整数型を使用しないでください –

答えて

7

1 << 31は、ほとんどのプラットフォーム上で未定義の動作である(例えば、16ビットまたは32ビットintを有するシステム)の結果としては、int(式の結果の型)で表現することができません。その式をコードで使用しないでください。一方、1U << 31は、結果がunsigned int(結果の式の型)で表現できるように、32ビットのintを持つシステムで有効な式です。

32ビットのintシステムでは、0x80000000は、タイプunsigned intの(比較的)大きな正の整数です。 1 << 31式を使用して鼻から飛んでくる悪魔がいないほど運が良ければ、INT_MINとなり、(負の)負の整数値はintとなります。

+0

申し訳ありませんが、すでに質問に回答しています – gmug

1

0x80000000は、その数値を表すために32ビットを必要とする大きな数値です。これは、32ビットシステム(または32ビット互換アプリケーション)では、intが小さすぎることを意味します。代わりにunsigned longを使用してください。

#define SCALE (1u << 31) 

#define fix_Q31_80(x) ((unsigned long) ((float)(x)*(float)0x80000000u)) 
#define fix_Q31_SC(x) ((unsigned long) ((float)(x)*(float)SCALE  )) 

int main() 
{ 
    unsigned long fix_80 = fix_Q31_80(0.5f); 
    unsigned long fix_sc = fix_Q31_SC(0.5f); 
} 
2

すべての整数定数には型があります。 1の場合、タイプはintです。 32ビット整数のシステムでは、1 << 31は数値が大きすぎてintとして表されません。これは未定義の動作であり、したがってバグです。

しかし、0x80000000は、32ビットシステムではunsigned intになるため、期待どおりに動作します。これは、10進定数と16進定数は、コンパイラがどの型を持つべきか調べるときに、異なる動作をするためです(as explained here)。

いくつかの人が触れたように、符号付きの型にはビット演算子を使用しないでください。

関連する問題