问题
I have the following variable
uint32_t Value = 0x80
0x80 represents an address in the memory e.g.
// Write 2 at address 0x80
*(uint32_t*)((uint32_t)0x80) = 2;
How can i cast Value to a Pointer, so it points to 0x80?
uint32_t *Pointer = ?? Value;
This:
(uint32_t*)(uint32_t)Value;
returns:
warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
回答1:
To handle integer to object pointer conversion, use the optional integer uintptr_t
or intptr_t
types. Function pointers are a separate matter.
The following type designates an unsigned integer type with the property that any valid pointer to
void
can be converted to this type, then converted back to pointer tovoid
, and the result will compare equal to the original pointer C11dr 7.20.1.4 1
uintptr_t
Then convert the void *
to the desired type.
#include <stdint.h>
uintptr_t Value = 0x80;
uint32_t *Pointer = (void *) Value;
If 0x80 was not derived from a valid uint32_t *
, the result in undefined behavior (UB). Yet it sounds like OP is on a platform with memory mapped data locations.
回答2:
I will spell it out for you: given
uint32_t Value = 0x80;
you want
*((uint32_t *)(uintptr_t)Value) = 2;
The type uintptr_t
, if it exists, is guaranteed to be castable to and from arbitrary pointer types without loss of information. It is not guaranteed to exist, but on platforms where it doesn't exist, what you're trying to do cannot safely be done without a great deal more information.
No other type is officially guaranteed to have this property; however, "cpp plus 1" is correct that size_t
usually also does. I would go so far as to say that any ABI for a flat-memory architecture, that doesn't make size_t
have this property, was specified incorrectly, but they do exist and sometimes you have to work with them.
It would be better to declare Value
with a pointer type in the first place:
uint32_t *const Value = (uint32_t *)(uintptr_t)0x80;
because then you only have to write the casts when you initialize it, not when you use it,
*Value = 2;
and you probably have a bunch of places where you use it. This also avoids a potential problem if it happens that sizeof(uintptr_t) < sizeof(uint32_t)
, as uint32_t
is never involved in the address arithmetic; the compiler may complain if the cast from 0x80
to uintptr_t
actually truncates the constant, but that shouldn't ever happen with the real memory addresses you are accessing this way.
来源:https://stackoverflow.com/questions/45220134/how-to-cast-integer-value-to-pointer-address-without-triggering-warnings