473,322 Members | 1,703 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

pointer to integer to pointer conversions

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.

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)?

On the document 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?

I gather that this document is about C99, is the answer different in
C89?

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?

In any case it works, is there a portable way to know what integer
types are large enough to hold a pointer value?

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 portability in that case, but I have the feeling
that it might be useful knowledge later on. Or maybe I'm only
overemphasizing portability the same way too many people overemphasize
performance.
Jun 27 '08 #1
12 3239
On May 6, 3:05 pm, lithium...@gmail.com 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.hto 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 = malloc(123); foo = ~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 converted
back to pointer to void, and the result will compare equal to the originalpointer.
(regarding intptr_t and uintptr_t)
On the document 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?
From 6.3.2.3:
Any pointer type may be converted to an integer type. Except as previouslyspecified, 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.
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 document 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 portable 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 portability in that case, but I have the feeling
that it might be useful knowledge later on. Or maybe I'm only
overemphasizing portability 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.
Jun 27 '08 #2
li********@gmail.com 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.

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)?
"It depends."

In C89/C90/ANSI, conversions from data pointer to integer and
back are permitted, but there are no guarantees about the values
you'll get and no guarantees that any given value will survive
the round-trip. (The commonest reason for non-survival is that
the integer is too short: a program that converted pointers to
32-bit ints finds itself ported to a machine with 64-bit pointers.)

C99 improves the situation, but only a little. If the integer
types intptr_t and uintptr_t exist, then any valid void* can be
converted to one of them and back again and survive the journey.
(There are no guarantees for invalid pointers, nor for converting
an arbitrary integer value to void* and back.) Note, though, that
these integer types are optional: If they exist they will work as
you desire, but on some "exotic" architecture they might be absent.
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?
The operations on intptr_t and uintptr_t are defined only for
valid void* values, but a valid AnyData* can always be converted
to void* and back without harm. So you should write

AnyData *p = &whatever, *q;
uintptr_t ip;
ip = (uintptr_t)(void*)p;
q = (void*)ip;
assert (p == q);

As far as I can tell, all the casts are necessary.
In any case it works, is there a portable way to know what integer
types are large enough to hold a pointer value?
For C99, intptr_t and uintptr_t are the answers. I cannot
think of a Simon-pure way to solve the problem for earlier Standards.
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 portability in that case, but I have the feeling
that it might be useful knowledge later on. Or maybe I'm only
overemphasizing portability the same way too many people overemphasize
performance.
Even in C89 you could printf a void* value with "%p". You
could also scanf it with "%p" (matching a void**), but the result
was not usefully defined. C99 (or maybe an intermediate revision)
tightened the language to require that the round-trip must succeed
if everything was valid to begin with, the program hasn't exited,
the pointed-to location is still valid, and so on.

I can understand why you'd want to display pointer values as
a debugging aid, but it seems peculiar to want to read them back
again. Chancy, too: An innocent typo arouses the nasal demons.

--
Eric Sosman
es*****@ieee-dot-org.invalid
Jun 27 '08 #3
Thanks you all for your answers, they were really helpful. It seems
that 6.3.2.3 wasn't all.

Although it's quite off-topic, could you tell me what that
"ISO/IEC 1999:TC3" is worth? Can I take it as a reference? If so, is
there a similar reference for C89?

On May 6, 2:37 pm, Eric Sosman <esos...@ieee-dot-org.invalidwrote:
Even in C89 you could printf a void* value with "%p". You
could also scanf it with "%p" (matching a void**), but the result
was not usefully defined. C99 (or maybe an intermediate revision)
tightened the language to require that the round-trip must succeed
if everything was valid to begin with, the program hasn't exited,
the pointed-to location is still valid, and so on.
Thanks a lot for the idea, I haven't even considered it. I've
actually never used any scanf-like function. I don't like using
things I don't understand, and these functions looks a little bit
like magic to me. I will dig into that direction.

Now that I think about it, I made the mistake of only considering
giving the pointer to the user as an int, while actually I want to
give it as a printable string.
I can understand why you'd want to display pointer values as
a debugging aid, but it seems peculiar to want to read them back
again. Chancy, too: An innocent typo arouses the nasal demons.
I don't know if it's a usual or good way to do it, but I like to
test parts of my programs "by hand", without any input santization
and as little processing as possible (I want to test the part of
my program, not the draft-input I put on it for testing/debugging
purpose). In these cases, an "innocent typo" only means that I
can't deduce anything from the test, which isn't that bad (though
I should probably consider myself lucky to encounter only program
segfaults as manifestations of undefined behaviour, and not e.g.
large-scale nuclear explosions).
Jun 27 '08 #4
li********@gmail.com writes:
Thanks you all for your answers, they were really helpful. It seems
that 6.3.2.3 wasn't all.

Although it's quite off-topic, could you tell me what that
"ISO/IEC 1999:TC3" is worth? Can I take it as a reference? If so, is
there a similar reference for C89?
I presume you're referring to n1256.pdf, available at
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>.

That's not a completely official document, but it's good enough for
most practical purposes. It includes the offical C99 standard plus
the changes made by the three Technical Corrigenda. Any changes
introduced by the TCs are marked with change bars. It's what I use
most of the time.

If you want something absolutely official, you can get a copy of the
C99 standard itself (without the TCs) by paying money to your national
standards body. I got mine from ANSI for something like $18; I think
it's gone up slightly since then. You should be able to get TC1, TC2,
and TC3 from the same source at no charge. Flipping back and forth
between the C99 standard and the changes in the TCs is tedious --
which is why n1256.pdf is so handy.

Good copies of the C89/C90 standard are a bit harder to come by. I
have a poor-quality PDF copy that I bought from ANSI for $18, but I
don't think it's available anymore. Some pre-C89 drafts are freely
available; I expect that someone will post URLs any minute now.

At least one person here prefers (I think it's) n869.txt. This is a
pre-C99 draft, *not* a C89/C90 draft. It has the advantage that it's
in plain text rather than PDF. It has the disadvantage that it's in
plain text rather than PDF. In particular, some semantically
significant formatting, particularly the use if italics, is lost --
and there were some changes between n869 and the final C99 standard.
I don't recommend it unless you have serious problems dealing with PDF
documents.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #5
Keith Thompson wrote, On 06/05/08 20:46:
li********@gmail.com writes:
>Thanks you all for your answers, they were really helpful. It seems
that 6.3.2.3 wasn't all.

Although it's quite off-topic, could you tell me what that
"ISO/IEC 1999:TC3" is worth? Can I take it as a reference? If so, is
there a similar reference for C89?

I presume you're referring to n1256.pdf, available at
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>.
<snip>
don't think it's available anymore. Some pre-C89 drafts are freely
available; I expect that someone will post URLs any minute now.
Links to I think all the relevant documents, including that one, can be
found at http://clc-wiki.net/wiki/c_standard
At least one person here prefers (I think it's) n869.txt. This is a
pre-C99 draft, *not* a C89/C90 draft. It has the advantage that it's
<snip>
I don't recommend it unless you have serious problems dealing with PDF
documents.
I second that. If you want a C99 draft the post C99 drafts are a lot
more useful.
--
Flash Gordon
Jun 27 '08 #6
Eric Sosman <es*****@ieee-dot-org.invalidwrote:
C99 improves the situation, but only a little. If the integer
types intptr_t and uintptr_t exist, then any valid void* can be
converted to one of them and back again and survive the journey.
(There are no guarantees for invalid pointers, nor for converting
an arbitrary integer value to void* and back.) Note, though, that
these integer types are optional: If they exist they will work as
you desire, but on some "exotic" architecture they might be absent.
On the upside, if your architecture is exotic enough that it has a C99
implementation but no (u)intptr_t, it's probably not reliably possible
to do this in the first place. So if including <stdint.hdoesn't result
in a definition of UINTPTR_MAX, bailing out with an #error would
probably have been your best option anyway.

BTW, I still don't understand why we have both intptr_t and uintptr_t.
We really only need either of those.

Richard
Jun 27 '08 #7
On May 7, 11:17 am, r...@hoekstra-uitgeverij.nl (Richard Bos) wrote:
Eric Sosman <esos...@ieee-dot-org.invalidwrote:
C99 improves the situation, but only a little. If the integer
types intptr_t and uintptr_t exist, then any valid void* can be
converted to one of them and back again and survive the journey.
(There are no guarantees for invalid pointers, nor for converting
an arbitrary integer value to void* and back.) Note, though, that
these integer types are optional: If they exist they will work as
you desire, but on some "exotic" architecture they might be absent.

On the upside, if your architecture is exotic enough that it has a C99
implementation but no (u)intptr_t, it's probably not reliably possible
to do this in the first place. So if including <stdint.hdoesn't result
in a definition of UINTPTR_MAX, bailing out with an #error would
probably have been your best option anyway.

BTW, I still don't understand why we have both intptr_t and uintptr_t.
We really only need either of those.
I explained that in my other post.
vippstar wrote:
That's possible. Using `intptr_t' or `uintptr_t'.
You have to include <stdint.hto 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 = malloc(123); foo = ~foo; free((void*)~free);
^ ^^^^
With intptr_t undefined behavior might be invoked in this example (if,
for example, malloc() returns NULL)
Ignore the small error I made (typing free instead of foo), and that I
did not cast malloc(123) to (uintptr_t), which might be necessary.
The point of this snip is to show that ~ in signed integer with value
0 might be a trap representation, which you can avoid by using an
unsigned integer. I cannot think of an example that signed is
preferred to unsigned, but there has to be at least one.
Jun 27 '08 #8
"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
news:48*****************@news.xs4all.nl...
Eric Sosman <es*****@ieee-dot-org.invalidwrote:
> C99 improves the situation, but only a little. If the integer
types intptr_t and uintptr_t exist, then any valid void* can be
converted to one of them and back again and survive the journey.
(There are no guarantees for invalid pointers, nor for converting
an arbitrary integer value to void* and back.) Note, though, that
these integer types are optional: If they exist they will work as
you desire, but on some "exotic" architecture they might be absent.

On the upside, if your architecture is exotic enough that it has a C99
implementation but no (u)intptr_t, it's probably not reliably possible
to do this in the first place. So if including <stdint.hdoesn't result
in a definition of UINTPTR_MAX, bailing out with an #error would
probably have been your best option anyway.

BTW, I still don't understand why we have both intptr_t and uintptr_t.
We really only need either of those.
.... on any given system. I know of one system that defines pointers to be
signed, so storing them in a signed integer type makes sense, particularly
if one wants to (non-portably) manipulate them. On most other systems I'm
familiar with, pointers are unsigned, so you'd want to store them in an
unsigned integer type.

More practically speaking, I bet both exist simply because it's symmetric
and doesn't hurt. It also stops people from typing "unsigned intptr_t" if
that's what they want...

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking

Jun 27 '08 #9
Richard Bos wrote:
BTW, I still don't understand why we have both intptr_t and
uintptr_t. We really only need either of those.
Because of 6.2.5p6, "For each of the signed integer types,
there is a corresponding (but different) unsigned integer..."

--
Peter
Jun 27 '08 #10
vipps...@gmail.com wrote:
vippstar wrote:
That's possible. Using `intptr_t' or `uintptr_t'.
You have to include <stdint.hto 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 = malloc(123); foo = ~foo; free((void*)~free);
^ ^^^^
With intptr_t undefined behavior might be invoked in this
example (if, for example, malloc() returns NULL)

Ignore the small error I made (typing free instead of foo), and
that I did not cast malloc(123) to (uintptr_t), which might be
necessary.
It is.
The point of this snip is to show that ~ in signed integer with
value 0 might be a trap representation, which you can avoid
by using an unsigned integer. I cannot think of an example
that signed is preferred to unsigned, but there has to be at
least one.
There are hashing techniques that involve negative values.
[Note that Java has no unsigned types.]

--
Peter
Jun 27 '08 #11
"Stephen Sprunk" <st*****@sprunk.orgwrites:
"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
news:48*****************@news.xs4all.nl...
[...]
>BTW, I still don't understand why we have both intptr_t and uintptr_t.
We really only need either of those.
[...]
>
More practically speaking, I bet both exist simply because it's
symmetric and doesn't hurt. It also stops people from typing
"unsigned intptr_t" if that's what they want...
There's also the fact that you can't legally apply "unsigned" to a
typedef.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #12
Peter Nilsson <ai***@acay.com.auwrote:
Richard Bos wrote:
BTW, I still don't understand why we have both intptr_t and
uintptr_t. We really only need either of those.

Because of 6.2.5p6, "For each of the signed integer types,
there is a corresponding (but different) unsigned integer..."
That's the most reasonable argument I've yet seen.

Richard
Jun 27 '08 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

22
by: Alex Fraser | last post by:
From searching Google Groups, I understand that void pointer arithmetic is a constraint violation, which is understandable. However, generic functions like qsort() and bsearch() must in essence do...
9
by: Juggernaut | last post by:
I am trying to create a p_thread pthread_create(&threads, &attr, Teste, (void *)var); where var is a char variable. But this doesnt't work, I get this message: test.c:58: warning: cast to pointer...
204
by: Alexei A. Frounze | last post by:
Hi all, I have a question regarding the gcc behavior (gcc version 3.3.4). On the following test program it emits a warning: #include <stdio.h> int aInt2 = {0,1,2,4,9,16}; int aInt3 =...
10
by: vb | last post by:
Hi all, I am a newbie in C and i want to know what all pointer conversions are "legal" according to ANSI C standard. For Example, int* to char*, some_struct* to char* and so on .. According to...
9
by: junky_fellow | last post by:
Hi, To print the pointer using printf(), we convert it to (void *) . printf("%p",(void *)ptr); My question is how printf() determine which type of pointer is passed to it and prints its value...
11
by: quakewang | last post by:
hi, I have define in a head file like this: #define GLUT_BITMAP_9_BY_15 ((void*)2) #define GLUT_BITMAP_8_BY_13 ((void*)3) #define GLUT_BITMAP_TIMES_ROMAN_10 ...
156
by: Lame Duck | last post by:
Hi Group! I have a vector<floatvariable that I need to pass to a function, but the function takes a float * arguement. That's OK, I can convert by doing &MyVector.front(), but when I get back a...
17
by: Ivan K. | last post by:
I am looking at some legacy code, which begins by allocating a double matrix with the dmatrix() function from NRC as follows: double **A, **augin, **augout, **aa; A = dmatrix(1,...
41
by: simonl | last post by:
Hi, I've been given the job of sorting out a crash in our product for which we have the crash information and an avi of the event (which can't possibly match but more of that later...) (btw this...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shllpp 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.