以下代码
static inline float fix2float(int64_t f)
{
return (float)f / (1 << 60); // <-- error here
}
编译器正在给我这些警告。
warning: left shift count >= width of type
warning: division by zero
为什么编译器在64&gt;时发出这些警告? 60?
答案 0 :(得分:9)
1
不是C实现中的64位数字。它是int
,可能是32位。
编译器不查看表达式并看到涉及int64_t
,因此其他算法应使用64位。它从它们的部分构建表达式。在(1 << 60)
部分中,编译器识别一个并给它一个int
类型,因为这就是C规则对简单常量值所说的(对于十六进制表示法有后缀,后缀,和大的价值观)。因此,1 << 60
尝试将int
移位60位。由于系统上的int
只有32位,编译器会发出警告。
更好的方法是return f * 0x1p-60f;
。 0x1p-60f
是一个float
常量,值为2 -60 。
答案 1 :(得分:3)
在您的代码中,存在与int64_t实际上没有关系的错误。在(1 << 60)
表达式中,1
和60
都被视为int(通常为32位)。您应该使用修饰符LL
。
像(1LL&lt;&lt; 60)。
#include <stdio.h>
int main()
{
printf("%llx\n", (1LL << 60));
return 0;
}
顺便提一下,请注意printf()
格式。 int64_t
实际上是long long
(至少在大多数情况下)。
更新:有社区声音建议使用稍微不同的方法:
printf("%" PRIx64 "\n", (UINT64_C(1) << 60));
这里的问题至少在我的领域并非所有编译器都能正确实现这些宏(这里是one of possible proofs)。但主流编译器应该感到高兴。至少我不建议在GCC中混合使用%lld
和1LL
(你可以尝试,至少GCC 4.6.3抱怨这种混合)。