Casting a pointer to an int and back

P

pinkfloydhomer

Is it well-defined to make a cast from a pointer to an int and back?
Like:

typedef struct
{
int whatever;
} S;

int main(void)
{
S* s = malloc(sizeof(S));
int i = (int) s;
S* t = (S*) i;
t.whatever = 42;
etc.
}

/David
 
V

Vladimir S. Oka

Is it well-defined to make a cast from a pointer to an int and back?

No, it is not.

You may be lucky that it works on your implementation, but don't count
on it (i.e. it's not portable).

Some concerns:

- how do pointers map to integers?
- how do integers map to pointers (not necessarily same as above)?
- is an integer wide enough to hold an address value (even if above is
fine)?

Even if all of the above are fine for one implementation/architecture,
the may not be on others.

Just don't do it. Also, have a look at other things you got wrong,
below:

#include <stdlib.h>

Otherwise `malloc` is unknown.
typedef struct
{
int whatever;
} S;

int main(void)
{
S* s = malloc(sizeof(S));
int i = (int) s;
S* t = (S*) i;
t.whatever = 42;

You certainly mean:

t->whatever = 42;

or

(*t).whatever = 42;

This is a syntax error.

Please post full, compileable, minimal examples.
 
G

Grumble

Is it well-defined to make a cast from a pointer to an
int and back?

I don't think so.

For example, on some platforms,
sizeof(int) = 4 and sizeof(void *) = 8
 
V

Vladimir S. Oka

Richard said:
Well spotted. Go to top of the pedants class.

Yes! I finally made it!

Snipping relevant parts of the post is bad etiquette. I also said:

Which was the whole point. It's in the OP's interest, really.
 
S

SM Ryan

# Is it well-defined to make a cast from a pointer to an int and back?
# Like:

You can cast to some integer, but not necessarily an int. However
because so much legacy code depends on this working, compilers
will generaly do whatever is necessary to make it work.

You shouldn't need to cast ints to/from pointers anymore unless
you need to enter absolute address or similar issues. (void*)
can be assigned any data pointer the same way int used to be
a universal pointer type.
 
R

Richard Bos

Is it well-defined to make a cast from a pointer to an int and back?
Like:

typedef struct
{
int whatever;
} S;

int main(void)
{
S* s = malloc(sizeof(S));
int i = (int) s;
S* t = (S*) i;
t.whatever = 42;
etc.
}

On two conditions:
- that the cast from pointer to int doesn't lose any information, i.e.,
that an int is wide enough to hold all pointer values;
- that the pointer is cast to int and then back to the _same_ pointer
type;
AFAICT this is well-defined.

The second condition, only you yourself have any influence over. Just
don't convert a pointer to an integer and then to a different pointer
type. In this case, you're OK.
The first depends on the platform. If you have C99, you may be able to
use (u)intptr_t, which are integer types (not necessarily ints) capable
of holding any void * value safely. Declare i as intptr_t, and cast s to
void * before assigning it to i, and back the other way 'round, too:

intptr i = (int)(void *)s;.
S *t = (void *)i;

You don't need a cast to (S *) in the second line, since a void * will
be automatically and correctly converted to any object pointer type.
Unfortunately, these types are optional, and they don't exist in C89 at
all. If it's unavailable to you, you may just have to resort to using
unsigned long (or unsigned long long) and hoping that that's large and
well-aligned enough. It probably is, but it's not guaranteed. If you
have intptr_t, use it.

Richard
 
A

ais523

SM said:
# Is it well-defined to make a cast from a pointer to an int and back?
# Like:

You can cast to some integer, but not necessarily an int. However
because so much legacy code depends on this working, compilers
will generaly do whatever is necessary to make it work.
I believe C99 provides a typedef that's guaranteed to be some sort of
int large enough to hold any sort of pointer.
 
R

Richard G. Riley

Yes! I finally made it!

Snipping relevant parts of the post is bad etiquette. I also said:


Which was the whole point. It's in the OP's interest, really.

The snipped part had no relevance on my pithy reply to your pedant
prize winning reply. The guy was asking a question about casting : not for a
code review or smart assed comments on "etc." being a syntx error.

The fact that he didnt put in the includes and did include the ".etc"
would, to me, indicate that he was pseudo coding a bit to get an
answer to the pertient question which was "can one cast between
pointers and ints". I'm sure many others would have made this leap in
logic too : it is, after all, a programming language group :)

Or do you insist on working, compilable code for all questions on
casts?

Come on. Admit it. You were over the top
 
V

Vladimir S. Oka

Richard said:
The snipped part had no relevance on my pithy reply to your pedant
prize winning reply. The guy was asking a question about casting : not for a
code review or smart assed comments on "etc." being a syntx error.

Which question I answered /first/, and than added a few comments as
well. What is your problem with this?
The fact that he didnt put in the includes and did include the ".etc"
would, to me, indicate that he was pseudo coding a bit to get an
answer to the pertient question which was "can one cast between
pointers and ints". I'm sure many others would have made this leap in
logic too : it is, after all, a programming language group :)

He obviously wasn't "pseudocoding". His "pseudocode" looked very much
like an attempt at a C program. It actually wasn't even required to
support his question, especially not with the struct.
Or do you insist on working, compilable code for all questions on
casts?

Not necessarily working (otherwise there'll be no question, right? ;-)
), but certainly compilable (and not just for the cast questions). Or,
do you always re-type the posted code to try it out?
Come on. Admit it. You were over the top

Continuing to indulge you? I admit to that.
 
R

Richard G. Riley

Which question I answered /first/, and than added a few comments as
well. What is your problem with this?

You dont see how hiliting that "etc." was a syntax error is extreme to
say the least?
Continuing to indulge you? I admit to that.

I shall absolve you from doing so then. You may depart.

"etc. is a syntax error".LOL. It'll make a nice .sig I think.
 
P

pete

Richard said:
On two conditions:
- that the cast from pointer to int doesn't lose any information,
i.e.,
that an int is wide enough to hold all pointer values;
- that the pointer is cast to int and then back to the _same_ pointer
type;
AFAICT this is well-defined.

AFAICT it's implementation defined.

N869
6.3.2.3 Pointers
[#5] An integer may be converted to any pointer type.
Except as previously specified, the result is
implementation-defined, might not be properly aligned, and
might not point to an entity of the referenced type.49)
[#6] Any pointer type may be converted to an integer type.
Except as previously specified, 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.
 
A

ais523

pete said:
Richard said:
On two conditions:
- that the cast from pointer to int doesn't lose any information,
i.e.,
that an int is wide enough to hold all pointer values;
- that the pointer is cast to int and then back to the _same_ pointer
type;
AFAICT this is well-defined.

AFAICT it's implementation defined.

N869
6.3.2.3 Pointers
[#5] An integer may be converted to any pointer type.
Except as previously specified, the result is
implementation-defined, might not be properly aligned, and
might not point to an entity of the referenced type.49)
[#6] Any pointer type may be converted to an integer type.
Except as previously specified, 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.

OK, it's implementation-defined. But from my reading of C99, it is
still possible either to do it portably or to discover that it can't be
done.
From WG14/N843 (C99 draft):
# 7.18.1.4 Integer types capable of holding object pointers
# 1 The following type designates a 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 original pointer:
# intptr_t
# 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 to void,
# and the result will compare equal to the original pointer:
# uintptr_t
# (These types need not exist in an implementation.)
(I don't have the final copy of C99 to check against.)

As INTPTR_MAX is defined in <stdin.h> if and only if intptr_t exists,
it is possible for the preprocessor to determine whether this is
possible or not. Here is some sample code (untested, because I don't
have a C99 compiler):

#include <stdio.h>
#include <stdint.h>

int main(void)
{
int a=6;
int* pa=&a;
#ifdef INTPTR_MAX
{
intptr_t ipt;
ipt=(intptr_t)pa;
*(int*)ipt=8;
printf("%d\n",a);
}
#else
puts("intptr_t doesn't exist.");
#endif
return 0;
}

AFAICT, this will be defined and produce the expected result (printing
8\n) on any implementation where intptr_t exists. If it doesn't, the
program can at least tell it's impossible and print an error message.
Of course, this won't work under C89.
 
M

Mark McIntyre

The snipped part had no relevance on my pithy reply to your pedant
prize winning reply. The guy was asking a question about casting : not for a
code review or smart assed comments on "etc." being a syntx error.

You've not been here long have you? If you had, you would be aware
that most regulars will review code *in its entirety*, partly on the
(often correct) assumption that the OP may be completely mistaken
about the cause of their bug, partly out of kindness.
The fact that he didnt put in the includes and did include the ".etc"
would, to me, indicate that he was pseudo coding

If you don't post the code that went wrong, how can someone diagnose
it? And if you want to post pseudocode, then say so.
Or do you insist on working, compilable code for all questions on
casts?

Yes.
Come on. Admit it. You were over the top

No, he wasn'.
Mark McIntyre
 
C

CBFalconer

Vladimir S. Oka said:
Richard G. Riley wrote:
.... snip ...


Not necessarily working (otherwise there'll be no question, right? ;-)
), but certainly compilable (and not just for the cast questions). Or,
do you always re-type the posted code to try it out?


Continuing to indulge you? I admit to that.

I think the time has come for the following sig.

--
+-------------------+ .:\:\:/:/:.
| PLEASE DO NOT F :.:\:\:/:/:.:
| FEED THE TROLLS | :=.' - - '.=:
| | '=(\ 9 9 /)='
| Thank you, | ( (_) )
| Management | /`-vvv-'\
+-------------------+ / \
| | @@@ / /|,,,,,|\ \
| | @@@ /_// /^\ \\_\
@x@@x@ | | |/ WW( ( ) )WW
\||||/ | | \| __\,,\ /,,/__
\||/ | | | jgs (______Y______)
/\/\/\/\/\/\/\/\//\/\\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
==============================================================

fix (vb.): 1. to paper over, obscure, hide from public view; 2.
to work around, in a way that produces unintended consequences
that are worse than the original problem. Usage: "Windows ME
fixes many of the shortcomings of Windows 98 SE". - Hutchison
 
R

Richard G. Riley

You've not been here long have you? If you had, you would be aware

Did you read the OP?
that most regulars will review code *in its entirety*, partly on the
(often correct) assumption that the OP may be completely mistaken
about the cause of their bug, partly out of kindness.

The review of the code wasnt the issue. The question about casting was.
If you don't post the code that went wrong, how can someone diagnose
it? And if you want to post pseudocode, then say so.

So you would have thought that "etc." was his code would you?

This discussion is nothing to do with whether real code should be
posted : of course it should when there is an issue with a bug.

My point of contention is that it doesnt take a genius to realise
that "etc." was not part of any code and the OP was simply asking a
question about casts.

I understood it (the OP) and, as you point out, I havent been "here" long.

Why it takes so many people to police posters looking for help is
foreign to me.
 
V

Vladimir S. Oka

CBFalconer said:
I think the time has come for the following sig.

Thank you!

I'm posting from the office today, and have to use Google, so I
couldn't easily find it.
 
R

Richard G. Riley

I think the time has come for the following sig.

LOL. Ridiculous. How can I be trolling when I am trying to argue
reasonably about *helping* a perfectly clear question? I'm sorry if my
standards of "input" are less exacting than your own. Sometimes
reading betweent the lines can be very rewarding
 
J

Jordan Abel

No, it is not.

You may be lucky that it works on your implementation, but don't count
on it (i.e. it's not portable).

It's not a matter of luck; the existence and identity of the integral
type that a pointer may be converted to and back is
implementation-defined [saying "lucky" implies that it is undefined]
Some concerns:

- how do pointers map to integers?
- how do integers map to pointers (not necessarily same as above)?
- is an integer wide enough to hold an address value (even if above is
fine)?

Even if all of the above are fine for one implementation/architecture,
the may not be on others.

and since it's implementation-defined, you can look it up in your
platform documentation. (OT: on many platforms, you probably want to use
a long instead of an int.)
 
J

Jordan Abel

# Is it well-defined to make a cast from a pointer to an int and back?
# Like:

You can cast to some integer, but not necessarily an int.

And not necessarily any at all. intptr_t is not required to exist, and
there is not required to be such a type. (OT: long is often more likely
to work than int - on linux, for example, the kernel only compiles on
systems where a pointer fits in a long)
However because so much legacy code depends on this working, compilers
will generaly do whatever is necessary to make it work.

You shouldn't need to cast ints to/from pointers anymore unless
you need to enter absolute address or similar issues. (void*)
can be assigned any data pointer the same way int used to be
a universal pointer type.

The universal pointer type was never int - it was char * before it was
void *.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,152
Latest member
LorettaGur
Top