解密有关无符号十进制常量的奇怪编译器警告

时间:2010-05-24 17:54:08

标签: c compiler-warnings

这个大型应用程序有一个内存池库,它在内部使用treap来存储内存节点。 treap是使用cpp宏实现的,可以找到完整的文件trp.h here。当我尝试编译应用程序时,我收到以下编译器警告:

warning: this decimal constant is unsigned only in ISO C90

通过删除部分宏代码并使用反复试验,我终于找到了罪魁祸首:

#define trp_prio_get(a_type, a_field, a_node)               \
    (2654435761*(uint32_t)(uintptr_t)(a_node))

我不确定那个奇怪的数字在那里做什么,但我认为这是有充分理由的,所以我只想不管它。我确实想修复警告 - 任何想法为什么编译器说它只在ISO C90中是无符号的?

编辑:我正在使用gcc-4.1

4 个答案:

答案 0 :(得分:6)

2654435761是对应于2 ^ 32的黄金比率数字。

  

在Knuth的“计算机艺术”中   编程“,第6.4节,a   乘法散列方案是   作为一种写哈希的方式介绍   功能。密钥乘以   黄金比例为2 ^ 32(2654435761)   产生哈希结果。

     

自2654435761和2 ^ 32没有   共同的共同因素,   乘法产生完整   将密钥映射到散列结果   没有重叠。这种方法效果很好   好吧,如果键值很小。   如果出现错误的哈希结果   密钥在高位有所不同。原样   在所有乘法中都是真的,   高位数的变化不会   影响的低位数   乘法结果。

http://www.concentric.net/~Ttwang/tech/inthash.htm

答案 1 :(得分:6)

尝试用

替换该号码
2654435761u

强制它无符号。

答案 2 :(得分:2)

我认为它是无符号的,因为它大于2,147,483,647,这是长有符号整数的最大大小,所以为了避免环绕,它将它视为无符号并发出警告。

答案 3 :(得分:2)

问题是这个常数2654435761大于2 ^ 31。这意味着对于较旧的编译器,它实际上将变为负值作为有符号常量。

现在,在这种情况下并不重要,因为由于乘以无符号值,它将被转换回无符号,并且正确的事情将会发生。