On May 6, 3:05 pm, lithium...@[EMAIL PROTECTED]
wrote:
> Hi,
>
> I bothered you a while back about storing integer values in void*. Now
> in a completely unrelated context, I'm trying to store pointer values
> in an integer type.
That's possible. Using `intptr_t' or `uintptr_t'.
You have to include <stdint.h> to use it.
There is also uintptr_t, which you will use to store the void pointer
does not matter.
The type only matters if you use it in arithmetic.
ie, uintptr_t foo =3D malloc(123); foo =3D ~foo; free((void*)~free);
With intptr_t undefined behavior might be invoked in this example (if,
for example, malloc() returns NULL)
> So the basic question is, is it possible to convert a pointer into an
> integer, and then later (but on the same execution environment, ie the
> program has not exited, thus it's the same architecture, same
> compiler, same binary representations and so on) retrieve from the
> integer the "same" pointer (that is, a pointer that points to the same
> object and that would compare equal to the original pointer if it was
> kept somewhere)?
Yep, quote from ISO 9899:1999, 7.18.1.4:
> The following type designates a (un)signed integer type with the
property
> that any valid pointer to void can be converted to this type, then
convert=
ed
> back to pointer to void, and the result will compare equal to the
original=
pointer.
(regarding intptr_t and uintptr_t)
> On the do***ent I found, named "ISO/IEC 9899:TC3", I have found on
> paragraph 6.3.2.3 that pointers can be converted into integers and
> vice versa, provided the integer type is large enough, the result
> being implementation-defined. Does it mean the standard does not
> guarantee that converting to an integer and back to a pointer yeilds
> the same pointer? Or is it written somewhere else?
=46rom 6.3.2.3:
> Any pointer type may be converted to an integer type. Except as
previously=
speci=EF=AC=81ed, the
> result is implementation-de=EF=AC=81ned. If the result cannot be
represent=
ed in the integer type,
> the behavior is unde=EF=AC=81ned. The result need not be in the range of
v=
alues of any integer
> type.
That means it's not safe to use any integer type other than intptr_t!
Even uintmax_t can invoke undefined behavior, when there is no
intptr_t or uintptr_t provided (they are optional types), and when a
pointer is larger than the largest integer type in the implementation.
> I gather that this do***ent is about C99, is the answer different in
> C89?
There's no answer in C89. In older code, unsigned long was used, but
that's not safe either.
It was obviously used it places where the details were known.
(compiler, platform, etc)
> And supposing that conversion might work, should I make sure the
> original pointer and the retrieved pointer have exactly the same type,
> or can it work with one them being of a given type and the other one
> being a void* later converted into a pointer of the correct type?
You have to cast the pointer to `void *' before you assign it to a
uintptr_t or intptr_t.
> In any case it works, is there a ****table way to know what integer
> types are large enough to hold a pointer value?
No.
> In case it matters, my situation is that I want, for debug purposes,
> to output the "value" of a pointer to the user (me), and then read
> that value back from the user. The most natural way to make a user
> handle pointers was to print and read it as an integer. Of course I
> don't really need ****tability in that case, but I have the feeling
> that it might be useful knowledge later on. Or maybe I'm only
> overemphasizing ****tability the same way too many people overemphasize
> performance.
You can also use the `p' conversion specifier in printf and scanf like
functions, which would probably be the best solution for your problem,
because it will also work in C89, and you don't have to worry about
the availability of uintptr_t/intptr_t.
Also, yes: It is possible to write a pointer to a file stream with %p,
then read it back.


|