Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deciphering a queer compiler warning about unsigned decimal constant

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 portions 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

like image 379
artagnon Avatar asked May 24 '10 17:05

artagnon


4 Answers

Try to replace that number with

2654435761u

to force it unsigned.

like image 136
kennytm Avatar answered Oct 03 '22 11:10

kennytm


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

like image 32
Amber Avatar answered Oct 03 '22 12:10

Amber


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.

like image 28
AndrejaKo Avatar answered Oct 03 '22 12:10

AndrejaKo


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.

like image 44
Chris Dodd Avatar answered Oct 03 '22 11:10

Chris Dodd