Storing a pointer in an int?

E

Evan Klitzke

I was browsing the documentation for GLib, and came across this:
http://library.gnome.org/devel/glib/stable/glib-Type-Conversion-Macros.html#GINT-TO-POINTER--CAPS

I was interested in the caveat that storing a pointer in an integer is
not portable. I'm not much of a C/C++ hacker so I was wondering: why
is this not portable? The best guess that I could come up with is that
on some architectures the size of a pointer might be larger than the
size of an int, e.g. on x86-64 Linux builds (with gcc/glibc anyhow) I
think pointers are 8 bytes and ints are 4 bytes. Is this the only
reason? Does the C standard guarantee the reverse -- that a pointer is
always at least as large as an int?

Inquiring minds want to know.
 
R

Richard Tobin

Evan Klitzke said:
I was interested in the caveat that storing a pointer in an integer is
not portable. I'm not much of a C/C++ hacker so I was wondering: why
is this not portable? The best guess that I could come up with is that
on some architectures the size of a pointer might be larger than the
size of an int

Yes, this is the main reason. There is usually some integer type that
is big enough, and in C99 the types intptr_t and uintptr_t are
provided for this purpose (though they are optional).

It's also conceivable that storing a opinter directly in an integer
type mught produce an illegal value, but this is a purely theoretical
possibility for most of us.
Does the C standard guarantee the reverse -- that a pointer is
always at least as large as an int?

No.

-- Richard
 
U

user923005

I was browsing the documentation for GLib, and came across this:http://library.gnome.org/devel/glib/stable/glib-Type-Conversion-Macro...

I was interested in the caveat that storing a pointer in an integer is
not portable. I'm not much of a C/C++ hacker so I was wondering: why
is this not portable? The best guess that I could come up with is that
on some architectures the size of a pointer might be larger than the
size of an int, e.g. on x86-64 Linux builds (with gcc/glibc anyhow) I
think pointers are 8 bytes and ints are 4 bytes.
/* Indeed... */
#include <stdio.h>

int main(void)
{
printf("sizeof (int) = %u, sizeof (void *) = %u\n",
(unsigned) sizeof (int), (unsigned) sizeof (void *));
return 0;
}
/*
My machine prints this:
sizeof (int) = 4, sizeof (void *) = 8
*/
Is this the only
reason? Does the C standard guarantee the reverse -- that a pointer is
always at least as large as an int?

No.
For data objects, this is a pretty handy guarantee from ISO/IEC
9899:1999 (E) 6.3.2.3 Pointers:
"1 A pointer to void may be converted to or from a pointer to any
incomplete or object type. A pointer to any incomplete or object type
may be converted to a pointer to void and back again; the result shall
compare equal to the original pointer."

The same section gives this grave warning:
"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."
 
J

James Kuyper

Evan said:
I was browsing the documentation for GLib, and came across this:
http://library.gnome.org/devel/glib/stable/glib-Type-Conversion-Macros.html#GINT-TO-POINTER--CAPS

I was interested in the caveat that storing a pointer in an integer is
not portable. I'm not much of a C/C++ hacker so I was wondering: why
is this not portable? The best guess that I could come up with is that
on some architectures the size of a pointer might be larger than the
size of an int, e.g. on x86-64 Linux builds (with gcc/glibc anyhow) I
think pointers are 8 bytes and ints are 4 bytes. Is this the only
reason? Does the C standard guarantee the reverse -- that a pointer is
always at least as large as an int?

The C standard doesn't guarantee that any integer type (not even
intmax_t) is big enough to store a pointer value. Nor does it guarantee
that any pointer type is big enough to store any integer type larger
than char.

If a given implementation does support a signed integer type big enough
to store a pointer value, then <stdint.h> will contain #definitions for
the macros INTPRT_MAX and INTPTR_MIN, and a typedef for that type with
the name intptr_t. The corresponding identifiers for an unsigned integer
type that's big enough are UINTPTR_MAX and uintptr_t; there is, of
course, no UINTPTR_MIN.
 
U

user923005

The C standard doesn't guarantee that any integer type (not even
intmax_t) is big enough to store a pointer value. Nor does it guarantee
that any pointer type is big enough to store any integer type larger
than char.

If a given implementation does support a signed integer type big enough
to store a pointer value, then <stdint.h> will contain #definitions for
the macros INTPRT_MAX and INTPTR_MIN, and a typedef for that type with
the name intptr_t. The corresponding identifiers for an unsigned integer
type that's big enough are UINTPTR_MAX and uintptr_t; there is, of
course, no UINTPTR_MIN.

I am curious as to why we would want to use these instead of void
pointers.
I can't think of any good reason.
 
J

jameskuyper

user923005 said:
I am curious as to why we would want to use these instead of void
pointers.
I can't think of any good reason.

The main reason I can think of is that they can be handled
numerically. Mathematical operations on such values have no standard-
defined meaning, thought they might have an implementation-specific
meaning (for instance, if a given type has an alignment requirement of
N, then it could be the case, for a particular implementation, that
the integer corresponding to a given pointer is exactly divisible by N
if and only if it that memory location is correctly aligned to hold an
object of that type).

However, for some applications (cryptography, for instance), the
meaning of those operations isn't important. Of course, it's perfectly
feasible to access an n-byte void* pointer as an array of unsigned
char, and to encrypt it as such. However, being able to treat an
entire intptr_t object as a single integer value could make such code
simpler.

Another example would be if for some reason you want to use a pointer
itself as a key field, rather than the value of the object it points
at. For algorithms like bsearch(), or for data structures such as
binary trees, you need some way to order all of the key field's
values. However, if you compare two pointers for order, the behavior
is undefined unless they both point into the same array. If you first
convert them to integers, it's perfectly safe to perform the
comparison. The standard doesn't guarantee what the result of the
comparison will be, though a particular implementation might. However,
for many situations the meaning of that order is less important than
the simple fact that a order can be determined.
 
D

Dik T. Winter

> The main reason I can think of is that they can be handled
> numerically. Mathematical operations on such values have no standard-
> defined meaning, thought they might have an implementation-specific
> meaning (for instance, if a given type has an alignment requirement of
> N, then it could be the case, for a particular implementation, that
> the integer corresponding to a given pointer is exactly divisible by N
> if and only if it that memory location is correctly aligned to hold an
> object of that type).

And just that led to one of the most flagrant cases of non-portable
programming that I encountered in a program that was assumed to be reasonably
portable, the Korn shell. It may work on machines that are byte-addressable,
but will not work on other machines (the Cray-1). The code assumed that it
could use the least significant bit of pointers (that would be sufficient
aligned for integers) as a flag. On the Cray-1 that was clearly false.
 
T

Tim Rentsch

jameskuyper said:
The main reason I can think of is that they can be handled
numerically. Mathematical operations on such values have no standard-
defined meaning, thought they might have an implementation-specific
meaning (for instance, if a given type has an alignment requirement of
N, then it could be the case, for a particular implementation, that
the integer corresponding to a given pointer is exactly divisible by N
if and only if it that memory location is correctly aligned to hold an
object of that type).

However, for some applications (cryptography, for instance), the
meaning of those operations isn't important. Of course, it's perfectly
feasible to access an n-byte void* pointer as an array of unsigned
char, and to encrypt it as such. However, being able to treat an
entire intptr_t object as a single integer value could make such code
simpler.

Another example would be if for some reason you want to use a pointer
itself as a key field, rather than the value of the object it points
at. For algorithms like bsearch(), or for data structures such as
binary trees, you need some way to order all of the key field's
values. However, if you compare two pointers for order, the behavior
is undefined unless they both point into the same array. If you first
convert them to integers, it's perfectly safe to perform the
comparison. The standard doesn't guarantee what the result of the
comparison will be, though a particular implementation might. However,
for many situations the meaning of that order is less important than
the simple fact that a order can be determined.

Also, this method of ordering isn't guaranteed to be well-defined, as
for example if we have pointers A, B, and C, with A == B, then
(int) A < (int) C && (int) B > (int) C may very well hold.
In fact, I don't think there's any guarantee that (int) A == (int) A
even though on most implementations it probably would be,
at least most of the time.
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top