开发者

Deciphering a queer compiler warning about unsigned decimal constant

开发者 https://www.devze.com 2022-12-31 16:33 出处:网络
This large application has a memory pool library which uses a treap internally to store nodes of memory. The treap is implemented using cpp macros, and the complete file trp.h can be found here. I get

This large application has a memory pool library which uses a treap internally to store nodes of memory. The treap is implemented using cpp macros, and the complete file trp.h can be found here. I get the following compiler warning when I attempt to compile the application:

warning: this decimal constant is unsigned only in ISO C90

By deleting port开发者_StackOverflow中文版ions of the macro code and using trial-and-error, I finally found the culprit:

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

I'm not sure what that strange number is doing there, but I assume it's there for a good reason, so I just want to leave it alone. I do want to fix the warning though- any idea why the compiler's saying that it's unsigned only in ISO C90?

EDIT: I'm using gcc-4.1


Try to replace that number with

2654435761u

to force it unsigned.


2654435761 is the golden ratio number corresponding with 2^32.

In Knuth's "The Art of Computer Programming", section 6.4, a multiplicative hashing scheme is introduced as a way to write hash function. The key is multiplied by the golden ratio of 2^32 (2654435761) to produce a hash result.

Since 2654435761 and 2^32 has no common factors in common, the multiplication produces a complete mapping of the key to hash result with no overlap. This method works pretty well if the keys have small values. Bad hash results are produced if the keys vary in the upper bits. As is true in all multiplications, variations of upper digits do not influence the lower digits of the multiplication result.

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


I think that it's unsigned because it's bigger than 2,147,483,647, which is the maximum size for long signed integer, so in order to avoid wrap-around, it's treating it as unsigned and giving warning.


The problem is that this constant 2654435761 is greater than 2^31. This means that with older compilers, it will actually turn into a negative value as a signed constant.

Now, in this case it doesn't matter, as due to being multiplied by an unsigned value, it will be converted back to unsigned, and the right thing will happen.

0

精彩评论

暂无评论...
验证码 换一张
取 消