Cast int to pointer - why cast to long first? (as in p = (void*) 42; )

sleske picture sleske · Aug 19, 2014 · Viewed 38.6k times · Source

In the GLib documentation, there is a chapter on type conversion macros. In the discussion on converting an int to a void* pointer it says (emphasis mine):

Naively, you might try this, but it's incorrect:

gpointer p;
int i;
p = (void*) 42;
i = (int) p;

Again, that example was not correct, don't copy it. The problem is that on some systems you need to do this:

gpointer p;
int i;
p = (void*) (long) 42;
i = (int) (long) p;

(source: GLib Reference Manual for GLib 2.39.92, chapter Type Conversion Macros ).

Why is that cast to long necessary?

Should any required widening of the int not happen automatically as part of the cast to a pointer?

Answer

askmish picture askmish · Aug 19, 2014

As according to the C99: 6.3.2.3 quote:

5 An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.56)

6 Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

According to the documentation at the link you mentioned:

Pointers are always at least 32 bits in size (on all platforms GLib intends to support). Thus you can store at least 32-bit integer values in a pointer value.

And further more long is guaranteed to be atleast 32-bits.

So,the code

gpointer p;
int i;
p = (void*) (long) 42;
i = (int) (long) p;

is safer,more portable and well defined for upto 32-bit integers only, as advertised by GLib.