...
Conversions between integers and pointers can have undesired consequences depending on the implementation. According to the C Standard, Section section 6.3.2.3 [ISO/IEC 9899:2011],
...
This example is noncompliant, for example, on an implementation where pointers are 64 bits and unsigned integers are 32 bits because the result of converting the 64-bit ptr
cannot be represented in the 32-bit integer type.:
Code Block | ||||
---|---|---|---|---|
| ||||
void f(void) { char *ptr; /* ... */ unsigned int number = (unsigned int)ptr; /* violation */ /* ... */ } |
...
Any valid pointer to void
can be converted to intptr_t
or uintptr_t
and back with no change in value (see INT11-EX2). The C Standard guaranteeds guarantees that a pointer to void
may be converted to or from a pointer to any object type and and back again and that the result must compare equal to the original pointer. Consequently, converting directly from a char *
pointer to a uintptr_t
, as in this compliant solution, is allowed on implementations that support the uintptr_t
type.
...
In this code example, the pointer ptr
is converted to an integer value. The high-order 9 bits of the number are used to hold a flag value, and the result is converted back into a pointer. This example is noncompliant, for example, on an implementation where pointers are 64 bits and unsigned integers are 32 bits because the result of converting the 64-bit ptr
cannot be represented in the 32-bit integer type.
...
It is sometimes necessary in low-level kernel or graphics code to access memory at a specific location, requiring a literal integer to pointer conversion. In this noncompliant code, a pointer is set directly to an integer constant, where it is unknown whether the result will be as intended.:
Code Block | ||||
---|---|---|---|---|
| ||||
unsigned int *g(void) { unsigned int *ptr = 0xdeadbeef; /* ... */ return ptr; } |
...
Adding an explicit cast may help the compiler convert the integer value into a valid pointer. A common technique is to assign the integer to a volatile-qualified object of type intptr_t
or uintptr_t
and then assign the integer value to the pointer. :
Code Block | ||||
---|---|---|---|---|
| ||||
unsigned int *g(void) { volatile uintptr_t iptr = 0xdeadbeef; unsigned int *ptr = (unsigned int *)iptr; /* ... */ return ptr; } |
...