使用我的新gcc编译器6.X版本获取此警告。
warning: result of '117901309 << 24' requires 52 bits to represent,
but 'int' only has 32 bits [-Wshift-overflow=]
我在代码中定义了一个带#define CLON 0x070707FD
的宏,该宏转换为警告中显示的十进制值。
当我在64位计算机上运行时,似乎int
占用了4个字节。但是我不确定它在早期的gcc版本上是如何运行的,比如4.X版本。任何人都可以帮我理解这个吗?
答案 0 :(得分:3)
新编译器警告您有关未定义的行为,旧编译器没有警告您。不胜感激,请完成升级到GCC 7.2.0,这是GCC的最新GA版本。
C11标准§6.5.7 Bitwise shift operators说:
E1 << E2
的结果是E1
左移E2
位位置;腾出的位充满了 零。如果E1
具有无符号类型,则结果的值为E1×2 E2 ,减少模数 比结果类型中可表示的最大值多一个。如果E1
已签名 类型和非负值,E1×2 E2 在结果类型中可表示,那么 结果价值;否则,行为未定义。
由于您的结果需要52位,因此无法在32位有符号整数中表示,并且编译器正确地警告您正在调用未定义的行为 - 这是您应该做的事情避免这样做。
解决问题的方法有很多种,但也许这是最简单的解决方法 - 使用CLON
后缀将unsigned
的类型更改为U
(或者您可以使用{{ 1}}甚至UL
如果您真的想要ULL
或unsigned long
结果):
unsigned long long
当该代码在文件#define CLON 0x070707FD
#define ULON 0x070707FDU
int shift_CLON(void);
unsigned shift_ULON(void);
int shift_CLON(void)
{
return CLON << 24;
}
unsigned shift_ULON(void)
{
return ULON << 24;
}
中时,您可以这样编译它:
sw73.c
答案 1 :(得分:1)
您需要指定要使用的显式大小。您需要将宏定义为
#define CLON 0x070707FDU
或者
#define CLON 0x070707FDL
答案 2 :(得分:0)
int
的大小确实是编译器/系统依赖的。然而,这并不是什么新鲜事,因此在早期版本中,代码并没有达到您的预期,只有在较新版本的情况下,它才会发出警告。
为了解决这个问题,请考虑在常量上使用显式位大小,例如117901309ll
。这里适当的几个取决于您的使用案例,无论如何我也考虑使用无符号值。