定义(1 << 31)还是使用0x80000000?结果不同

Dan*_*jel 4 c casting

#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);
}
Run Code Online (Sandbox Code Playgroud)

为什么价值观fix_80fix_sc不同?

fix_80 == Hex:0x40000000
fix_sc == Hex:0xc0000000
Run Code Online (Sandbox Code Playgroud)

oua*_*uah 9

1 << 31在大多数平台(例如,具有16位或32位的系统int)上是未定义的行为,因为其结果无法在int(表达式的结果类型)中表示.不要在代码中使用该表达式.另一方面,1U << 31在具有32位的系统上是有效表达式,int因为其结果可在unsigned int(表达式的结果类型)中表示.

在32位int系统上,0x80000000是一个(相对)大的正整数类型unsigned int.如果你幸运(或不幸)足以让恶魔通过使用1 << 31表达式飞出你的鼻子,这个表达式最可能的结果INT_MIN是一个(相对)大的负整数类型int.


Lun*_*din 5

所有整数常量都有一个类型。在 的情况下1,类型是int。在具有 32 位整数的系统上,1 << 31给出一个太大而无法表示为int. 这是未定义的行为,因此是一个错误。

但是0x80000000会按预期工作,因为在 32 位系统上它恰好是 type unsigned int。这是因为当编译器寻找它们应该具有的类型时,十进制常量和十六进制常量的行为不同,如此处解释

正如一些人所提到的,不要在有符号类型上使用按位运算符。