tags:

views:

517

answers:

4

hello, how can i get the memory address of the value a pointer points to? in my case it is a void pointer. just assigning it to an uint gives me this error:

Error   1 error C2440: 'return' : cannot convert from 'void *' to 'UInt32'

thanks!

+4  A: 
std::size_t address = reinterpret_cast<std::size_t>(voidptr);
// sizeof(size_t) must be greater or equal to sizeof(void*)
// for the above line to work correctly.


@Paul Hsieh
I think it is sufficient to convert void* to size_t in this specific question for three reasons:

  • The questioner didn't specify if he wants a portable solution or not. He said, that it worked with him. I don't know exactly what that means but it is clear to me he is working on IA-32 on Windows or other system under protected mode. That means converting a pointer to an integer is a defined operation on that system even if it is not defined by standard C++.

  • Second, I proposed first converting the pointer to int which is clearly meaningless as litb and jalf showed me. I corrected the mistake I've done, and replaced int with size_t.

  • Finally, I tried my hard to find something relevant to what you proposed as a solution in the standards. Unfortunately, I couldn't find anything relevant. I have this reference: ANSI ISO IEC 14882 2003. I think sellibitze pointed out that it will be part of the coming standards. I really don't know about C, and obviously C99 introduced this perfect solution. I would like someone to show me a portable solution in C++.

Please, don't hesitate to correct my mistakes, I am still a student at uni :)

Thanks,

AraK
On 64 bit systems sizeof(int) != sizeof (void *)
Paul Hsieh
A reinterpret_cast from a pointer to one of the integer types is only well-formed if the integer type is "big enough" so that a round trip pointer->integer->pointer is lossless.
sellibitze
No! It is very bad. Why was it accepted?
Alexey Malistov
In practice, `size_t` should be big enough on most boxes (but there is no guarantee in theory).
Johannes Schaub - litb
Even if we ignore the problem that int might be smaller than void*, you could *at least* have used an unsigned datatype. ;) Negative addresses aren't really meaningful.
jalf
Anyway, just edit your answer. Easier than waiting for it to be unaccepted so you can delete it. As long as it ends up being correct that's the main thing.
jalf
@jalf thanks for the advice.
AraK
hi, i accepted this answer cause it was the first one and it worked for me! in the meantime i also have put the recommended assert before.
clamp
Excuse me, but size_t is *NOT* sufficient. Think of "compact" mode for 16 bit x86 compilers. There size_t is still 16 bits, but the pointer is still a 16:16 segmented address (in which both parameters are significant.) The language will include a definition for ptrdiff_t, which is more likely to work.
Paul Hsieh
@Paul: We already have std::ptrdiff_t. Did you mean std::intrptr_t? @AraK: Yes, the C++0x will include std::intptr_t and std::uintptr_t. They are optional but if present shall be big enough to hold pointer values to objects and functions.
sellibitze
@AraK: IA-32 is a machine architecture, not an execution mode. Intel's 80386 processor (which is an IA-32) has a 16 bit protected mode in which pointers are selector:offset based, where sizeof (void *)=4 and sizeof (size_t)=2. You mean "32 bit execution mode" such as Win32.size_t really isn't the best type to use, when you have alternatives such as ptrdiff_t or intptr_t available to you. Think of size_t being just large enough to cover the largest thing malloc() could return to you, while ptrdiff_t and intptr_t clearly have to cover the entire pointer space range.
Paul Hsieh
@Paul Interesting I should learn x86, but it always seemed too complicated for me. I know little 68K, but that didn't help a lot as you have seen. Thanks for the correction again :)
AraK
"...while ptrdiff_t...clearly [has] to cover the entire pointer space range". @Paul: I don't think so. The language's memory model is "one or more sequences of consecutive bytes". Pointer arithmetic is restricted to pointers from the same "sequence". I think a ptrdiff_t doesn't have to be big enough to hold a pointer.
sellibitze
+2  A: 

You need a cast - either a reinterpret_cast (preferable):

UInt32 address = reinterpret_cast<UInt32>( voidPointer );

or a C-style cast (really not recommended):

UInt32 address = (UInt32)voidPointer;
sharptooth
I'd throw in an (BOOST) static assert on `sizeof(UInt32) == sizeof(void *)`
peterchen
Yeah, on 64 bit systems that's clearly wrong.
Paul Hsieh
+10  A: 

A pointer, in C and C++ is the embodiment of a memory address in some abstract form. You can get a implementation specific string interpretation of a pointer as:

printf ("%p", voidPointer);

Another way is to cast it to intptr_t:

(intptr_t) voidPointer;

The NULL pointer in C++ is defined as equal to "0", so presumably you would get the equiavlent of (intptr_t) 0 in the above operation. However it is still up to you and whatever implementation specific knowledge you have to interpret that as a memory address.

The point is that in platforms that use bizarre memory models such as 16 bit x86 DOS compilers, that have segments with offsets as their memory model, pointers can be interpreted in many ways. In a raw address representation NULL could be DS:0 or SS:0 rather than just a plain 0.

Paul Hsieh
intptr_t is not yet part of C++. Anyhow, are you sure that the standard guarantees (intptr_t)voidPointer to evaluate to 0 in case voidPointer is a null pointer and intptr_t is a proper typedef for an integer that is big enough? I don't think it does. It only says that if a pointer is casted to another pointer that the null pointer values are mapped to null pointer values. But a null pointer value for some pointer might actually be represented as something like 0xDEADBEEF -- not necessarily an integral zero.
sellibitze
-1 there is no guarantee in C++ that `(integer-type)null-pointer` evaluates to `0`, of course. You are confusing "NULL" with "null pointer". Read http://stackoverflow.com/questions/423823/whats-your-favorite-programmer-ignorance-pet-peeve/1331729#1331729
Johannes Schaub - litb
+1  A: 

You can get a string representation of the address with sprintf() or display it with printf() using the %p format specifier, e.g:

printf( "%p", voidptr ) ;

If you just want the address to perform pointer arithmetic on, cast it to an appropriate concrete data type pointer, otherwise cast it to an integer as already suggested.

Clifford