Storing a pointer in an int?

Discussion in 'C Programming' started by Evan Klitzke, Dec 23, 2008.

  1. Evan Klitzke

    Evan Klitzke Guest

    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.
     
    Evan Klitzke, Dec 23, 2008
    #1
    1. Advertising

  2. In article <>,
    Evan Klitzke <> wrote:

    >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
    --
    Please remember to mention me / in tapes you leave behind.
     
    Richard Tobin, Dec 23, 2008
    #2
    1. Advertising

  3. Evan Klitzke

    user923005 Guest

    On Dec 23, 1:09 am, Evan Klitzke <> wrote:
    > 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."
     
    user923005, Dec 23, 2008
    #3
  4. Evan Klitzke

    James Kuyper Guest

    Evan Klitzke wrote:
    > 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.
     
    James Kuyper, Dec 23, 2008
    #4
  5. Evan Klitzke

    user923005 Guest

    On Dec 23, 6:20 am, James Kuyper <> wrote:
    > Evan Klitzke wrote:
    > > 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. 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.


    I am curious as to why we would want to use these instead of void
    pointers.
    I can't think of any good reason.
     
    user923005, Dec 23, 2008
    #5
  6. Evan Klitzke

    jameskuyper Guest

    user923005 wrote:
    > On Dec 23, 6:20�am, James Kuyper <> wrote:

    ....
    > > 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.


    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.
     
    jameskuyper, Dec 23, 2008
    #6
  7. In article <> jameskuyper <> writes:
    ....
    > 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.
    --
    dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
    home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
     
    Dik T. Winter, Dec 24, 2008
    #7
  8. Evan Klitzke

    Tim Rentsch Guest

    jameskuyper <> writes:

    > user923005 wrote:
    > > On Dec 23, 6:20=EF=BF=BDam, James Kuyper <> wrote:

    > ...
    > > > 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 intege=

    > r
    > > > 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.

    >
    > 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.
     
    Tim Rentsch, Jan 8, 2009
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Schnoffos
    Replies:
    2
    Views:
    1,236
    Martien Verbruggen
    Jun 27, 2003
  2. Hal Styli
    Replies:
    14
    Views:
    1,681
    Old Wolf
    Jan 20, 2004
  3. Stormbringer
    Replies:
    18
    Views:
    525
    Samuel Walters
    Dec 30, 2003
  4. arun
    Replies:
    8
    Views:
    465
    Dave Thompson
    Jul 31, 2006
  5. toton
    Replies:
    11
    Views:
    721
    toton
    Oct 13, 2006
Loading...

Share This Page