Where do pointers point to?

Discussion in 'C Programming' started by x-pander, Jan 12, 2005.

  1. x-pander

    x-pander Guest

    Is is guaranteed, that a pointer to any object in C points exactly at the
    lowest addressed byte of this object?

    Specifcally is it possible for any platform/os/compiler combination that:
    (char *)v != (void *)v
    where v is an int variable for example.

    If so, any real-life examples?
    x-pander, Jan 12, 2005
    #1
    1. Advertising

  2. x-pander

    Ben Pfaff Guest

    "x-pander" <> writes:

    > Is is guaranteed, that a pointer to any object in C points exactly at the
    > lowest addressed byte of this object?


    Yes, as far as I know. (I'd love to hear intelligent
    disagreement on this, because I'd learn from it.)

    > Specifcally is it possible for any platform/os/compiler combination that:
    > (char *)v != (void *)v
    > where v is an int variable for example.


    Non sequitur: you just dragged in integer-to-pointer conversion,
    which is definitely non-portable.
    --
    "Give me a couple of years and a large research grant,
    and I'll give you a receipt." --Richard Heathfield
    Ben Pfaff, Jan 12, 2005
    #2
    1. Advertising

  3. x-pander

    x-pander Guest

    > Specifcally is it possible for any platform/os/compiler combination that:
    > (char *)v != (void *)v
    > where v is an int variable for example.


    CORRECTION, of course (!!!) i meant:
    (char *)&v != (void *)&v
    x-pander, Jan 12, 2005
    #3
  4. In article <cs1rtm$1irl$>,
    "x-pander" <> wrote:

    > Is is guaranteed, that a pointer to any object in C points exactly at the
    > lowest addressed byte of this object?
    >
    > Specifcally is it possible for any platform/os/compiler combination that:
    > (char *)v != (void *)v
    > where v is an int variable for example.


    A pointer points to the whole object.

    If you cast a pointer to another type, lets say from double* to int*,
    you get a pointer to an object that starts at the same place as the
    first object. So if you cast a pointer to char*, it points to the first
    byte of the object.

    You cannot compare char* and void*. In your example, the compiler will
    convert the (void *) v automatically to char*, so you are actually
    comparing

    (char *)v == (char *) (void *) v

    which is guaranteed to be equal.
    Christian Bau, Jan 12, 2005
    #4
  5. In article <>,
    Ben Pfaff <> wrote:

    > "x-pander" <> writes:
    >
    > > Is is guaranteed, that a pointer to any object in C points exactly at the
    > > lowest addressed byte of this object?

    >
    > Yes, as far as I know. (I'd love to hear intelligent
    > disagreement on this, because I'd learn from it.)


    It points to the "first" byte. The C Standard doesn't say anything about
    addresses.

    So if you have

    int x;
    char* p = (char *) &x;

    then the bytes of x are p [0], p [1], ..., p [sizeof (int) - 1], and not
    for example p [0], p [-1], p [-2] and so on.

    However, imagine you have an application of 10 million lines of code,
    non-portable because it is written under the assumption that your
    hardware is bigendian. You need to make it run on littleendian hardware.
    You have the source code to the compiler. Instead of changing 10 million
    lines of code, change the compiler so that the "first" byte is at a
    higher address than the last byte; where "p++;" would usually be
    translated into a hardware instruction that adds sizeof (*p), it will be
    translated to a hardware instruction that subtracts sizeof (*p). Pointer
    comparisons say that p < q if a hardware compare instruction says p > q
    and so on. Now a pointer always points to the highest addressed byte,
    and it is completely conforming and invisible to the programmer. The
    compiler turned a littleendian hardware into a bigendian implementation.
    (Code that casts pointers to unsigned int and checks the last bits for
    alignment will not work anymore; casting to and from integer will
    generally give strange results).
    Christian Bau, Jan 12, 2005
    #5
  6. x-pander

    x-pander Guest

    > If you cast a pointer to another type, lets say from double* to int*,
    > you get a pointer to an object that starts at the same place as the
    > first object. So if you cast a pointer to char*, it points to the first
    > byte of the object.


    I undesrtand that.

    > You cannot compare char* and void*. In your example, the compiler will
    > convert the (void *) v automatically to char*, so you are actually
    > comparing
    >
    > (char *)v == (char *) (void *) v
    >
    > which is guaranteed to be equal.


    So how about the result of the following comparision,
    which i think has a potential of effectively answering my original question:

    (int *)(char *)&v != &v
    x-pander, Jan 12, 2005
    #6
  7. Christian Bau <> writes:
    > In article <>,
    > Ben Pfaff <> wrote:
    >
    >> "x-pander" <> writes:
    >>
    >> > Is is guaranteed, that a pointer to any object in C points exactly at the
    >> > lowest addressed byte of this object?

    >>
    >> Yes, as far as I know. (I'd love to hear intelligent
    >> disagreement on this, because I'd learn from it.)

    >
    > It points to the "first" byte. The C Standard doesn't say anything about
    > addresses.


    Sure it does. Just one example, C99 6.5.3.1p3:

    The unary & operator returns the address of its operand.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Jan 12, 2005
    #7
  8. x-pander

    x-pander Guest

    > It points to the "first" byte. The C Standard doesn't say anything about
    > addresses.


    Actually it does:
    C99: 6.3.2.3.7
    "When a pointer to an object is converted to a pointer to a character type,
    the result points to the lowest addressed byte of the object. Successive
    increments of the result, up to the size of the object, yield pointers to
    the remaining bytes of the object."

    > You need to make it run on littleendian hardware.
    > You have the source code to the compiler. Instead of changing 10 million
    > lines of code, change the compiler so that the "first" byte is at a
    > higher address than the last byte; where "p++;" would usually be
    > translated into a hardware instruction that adds sizeof (*p), it will be
    > translated to a hardware instruction that subtracts sizeof (*p). Pointer
    > comparisons say that p < q if a hardware compare instruction says p > q
    > and so on. Now a pointer always points to the highest addressed byte,
    > and it is completely conforming and invisible to the programmer.


    An example situation in described system could be:

    int x;
    &x == 0x4003
    (void *)&x == 0x4003
    (char *)&x == 0x4000
    (void *)(char *)&x = 0x4000

    So:
    (void *)&x != (void *)(char *)&x

    In effect the following code would break (i've seen similar code in some
    libraries):

    void zero(void *ptr, int size)
    {
    memset(ptr, 0, size);
    }
    main()
    {
    int v;
    zero(&v, sizeof(v));
    }

    The solution is to always use char * instead of void *.

    Am I right?
    x-pander, Jan 12, 2005
    #8
  9. x-pander

    x-pander Guest

    > It points to the "first" byte. The C Standard doesn't say anything about
    > addresses.


    Actually it does:
    C99: 6.3.2.3.7
    "When a pointer to an object is converted to a pointer to a character type,
    the result points to the lowest addressed byte of the object. Successive
    increments of the result, up to the size of the object, yield pointers to
    the remaining bytes of the object."

    > You need to make it run on littleendian hardware.
    > You have the source code to the compiler. Instead of changing 10 million
    > lines of code, change the compiler so that the "first" byte is at a
    > higher address than the last byte; where "p++;" would usually be
    > translated into a hardware instruction that adds sizeof (*p), it will be
    > translated to a hardware instruction that subtracts sizeof (*p). Pointer
    > comparisons say that p < q if a hardware compare instruction says p > q
    > and so on. Now a pointer always points to the highest addressed byte,
    > and it is completely conforming and invisible to the programmer.


    An example situation in described system could be:

    int x;
    &x == 0x4003
    (void *)&x == 0x4003
    (char *)&x == 0x4000
    (void *)(char *)&x = 0x4000

    So:
    (void *)&x != (void *)(char *)&x

    In effect the following code would break (i've seen similar code in some
    libraries):

    void zero(void *ptr, int size)
    {
    memset(ptr, 0, size);
    }
    main()
    {
    int v;
    zero(&v, sizeof(v));
    }

    The solution is to always use char * instead of void *.

    Am I right?
    x-pander, Jan 12, 2005
    #9
  10. x-pander

    italy Guest

    You're cute, Ben Pfaff!
    italy, Jan 12, 2005
    #10
  11. x-pander

    Eric Sosman Guest

    x-pander wrote:
    >
    > So how about the result of the following comparision,
    > which i think has a potential of effectively answering my original question:
    >
    > (int *)(char *)&v != &v


    Guaranteed to work (evaluating to 0) if `v' is an `int'.

    Potential undefined behavior if `v' is not an `int': the
    conversion of any arbitrary (object) pointer to `char*' is
    well-defined, but even so this does not justify the subsequent
    attempt to convert a non-`int*' to an `int*'. There are a few
    cases is which this is guaranteed to work (e.g., if `v' is a
    struct whose first element is an `int'), but in general the
    conversion is not safe.

    --
    Eric Sosman
    lid
    Eric Sosman, Jan 12, 2005
    #11
  12. On Wed, 12 Jan 2005 01:41:37 +0000, Christian Bau wrote:

    > In article <cs1rtm$1irl$>,
    > "x-pander" <> wrote:
    >
    >> Is is guaranteed, that a pointer to any object in C points exactly at the
    >> lowest addressed byte of this object?
    >>
    >> Specifcally is it possible for any platform/os/compiler combination that:
    >> (char *)v != (void *)v
    >> where v is an int variable for example.

    >
    > A pointer points to the whole object.


    Right. An example is a an implementation on a word addressed architecture.
    Let's say int corresponds to the word size. A pointer to an int will point
    to the whole word on that architecture, it is incapable of pointing at a
    single byte. Additionally the implementation chooses to support bytes
    smaller than words by generating extra code to select the appropriate bits
    from the word. A character pointer therefore needs more information (i.e.
    which "byte" within the word to select) and will typically be larger than
    a word pointer, and a conversion between the two types of pointer will
    require a change of representation.

    > If you cast a pointer to another type, lets say from double* to int*,
    > you get a pointer to an object that starts at the same place as the
    > first object.


    That is likely but is not guaranteed. Taking the example above converting
    a char * to an int * can't achieve this if the character pointer doesn't
    point at a word boundary.

    > So if you cast a pointer to char*, it points to the first
    > byte of the object.


    The standard has a specific rule that guarantees this when you convert to
    pointers to character types, it isn't an example of a more general rule.

    > You cannot compare char* and void*. In your example, the compiler will
    > convert the (void *) v automatically to char*, so you are actually
    > comparing


    The char * operand is converted to void *. It doesn't matter here but
    is important for types other than pointers to characters.

    > (char *)v == (char *) (void *) v
    >
    > which is guaranteed to be equal.


    Yes, void * uses the same representation as pointers to character types.

    Lawrence
    Lawrence Kirby, Jan 12, 2005
    #12
  13. On Tue, 11 Jan 2005 22:27:34 -0500, Eric Sosman
    <> wrote:

    > x-pander wrote:
    >>
    >> So how about the result of the following comparision,
    >> which i think has a potential of effectively answering my original question:
    >>
    >> (int *)(char *)&v != &v

    >
    > Guaranteed to work (evaluating to 0) if `v' is an `int'.
    >
    > Potential undefined behavior if `v' is not an `int': the
    > conversion of any arbitrary (object) pointer to `char*' is
    > well-defined, but even so this does not justify the subsequent
    > attempt to convert a non-`int*' to an `int*'. There are a few
    > cases is which this is guaranteed to work (e.g., if `v' is a
    > struct whose first element is an `int'), but in general the
    > conversion is not safe.


    Am I correct in thinking that conversion of a T* to a char* is always
    safe (because sizeof char <= sizeof T for all types T) but the other way
    round may not be? For instance, an int* might be constrained to have
    some bits zero, so conversion to an int* with those bits set might
    either cause a hardware exception or 'silently' set the bits to zero.

    Chris C
    Chris Croughton, Jan 12, 2005
    #13
  14. x-pander

    S.Tobias Guest

    Christian Bau <> wrote:
    > In article <cs1rtm$1irl$>,
    > "x-pander" <> wrote:


    > > Is is guaranteed, that a pointer to any object in C points exactly at the
    > > lowest addressed byte of this object?


    I'd say it's impossible to tell, unless you convert your pointer
    to (char*), but then you're comparing different kind of pointers.

    > > Specifcally is it possible for any platform/os/compiler combination that:
    > > (char *)v != (void *)v
    > > where v is an int variable for example.


    > A pointer points to the whole object.


    > If you cast a pointer to another type, lets say from double* to int*,
    > you get a pointer to an object that starts at the same place as the
    > first object. So if you cast a pointer to char*, it points to the first
    > byte of the object.


    > You cannot compare char* and void*. In your example, the compiler will
    > convert the (void *) v automatically to char*, so you are actually
    > comparing


    No, (char*)v will be implicitly converted to (void*) (cf. 6.5.9#5)
    and void* pointers will be compared (although I can't see what possible
    difference it might make which way we do the conversion - later, the
    equality semantics doesn't depend on pointer type at all).

    > (char *)v == (char *) (void *) v


    > which is guaranteed to be equal.


    int v;
    (void*)(char*)&v == (void*)&v;

    I still don't see it (maybe it's obvious, but it's still early morning
    for me and a coffee didn't help). The Standard int 6.3.2.3 (Conversions ...
    Pointers) only demands that (subject to alignment) conversions between
    pointer types are reversible. However I don't see how you can infer
    from it that single int*->void* conversion must yield the same value
    as double conversion int*->char*->void*. How do you do it?

    Where exactly is it written that the result of pointer conversion
    (provided it doesn't invoke UB) must point to the same location
    as the original pointer?

    --
    Stan Tobias
    mailx `echo LID | sed s/[[:upper:]]//g`
    S.Tobias, Jan 12, 2005
    #14
  15. x-pander

    Michael Mair Guest

    Lawrence Kirby wrote:

    [snip: void * vs char *]

    > Yes, void * uses the same representation as pointers to character types.


    Are you sure of that? It is IMO logical but not necessary.

    I am not sure where but a couple of months ago there was a
    discussion where the example function execl() from the FAQ 5.2
    ( http://www.eskimo.com/~scs/C-faq/q5.2.html ) was cited and
    where some regulars stressed how important the cast (char *)
    is because execl is a function with variable argument list
    and so we need to make sure that we get (char *) NULL instead
    of plain (that is, (void *)) NULL.


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
    Michael Mair, Jan 12, 2005
    #15
  16. x-pander

    pete Guest

    Michael Mair wrote:
    >
    > Lawrence Kirby wrote:
    >
    > [snip: void * vs char *]
    >
    > > Yes, void * uses the same representation
    > > as pointers to character types.

    >
    > Are you sure of that?


    N869
    6.2.5 Types

    [#27] A pointer to void shall have the same representation
    and alignment requirements as a pointer to a character type.

    --
    pete
    pete, Jan 12, 2005
    #16
  17. On Wed, 12 Jan 2005 12:45:59 +0100, Michael Mair wrote:

    > Lawrence Kirby wrote:
    >
    > [snip: void * vs char *]
    >
    >> Yes, void * uses the same representation as pointers to character types.

    >
    > Are you sure of that? It is IMO logical but not necessary.


    6.2.5 says

    "A pointer to void shall have the same representation and alignment
    requirements as a pointer to a character type."

    > I am not sure where but a couple of months ago there was a discussion
    > where the example function execl() from the FAQ 5.2 (
    > http://www.eskimo.com/~scs/C-faq/q5.2.html ) was cited and where some
    > regulars stressed how important the cast (char *) is because execl is a
    > function with variable argument list and so we need to make sure that we
    > get (char *) NULL instead of plain (that is, (void *)) NULL.


    The case is important because NULL can be defined as, say, 0 i.e. have
    an integer type. This is certainly not guaranteed in any sense to have any
    representational equivalence to a pointer.

    There is a footnote for the standard text above that says:

    "The same representation and alignment requirements are meant to imply
    interchangeability as arguments to functions, return values from
    functions, and members of unions."

    which brings up the question of whether you are guaranteed to be able to
    pass a void * argument to a function that requires a char *. As the text
    suggests you are pretty safe in doing this. OTOH the footnote is not
    normative and the text of the standard makes no absolute guarantee.

    Lawrence
    Lawrence Kirby, Jan 12, 2005
    #17
  18. x-pander

    Eric Sosman Guest

    Chris Croughton wrote:
    > On Tue, 11 Jan 2005 22:27:34 -0500, Eric Sosman
    > <> wrote:
    >
    >
    >>x-pander wrote:
    >>
    >>>So how about the result of the following comparision,
    >>>which i think has a potential of effectively answering my original question:
    >>>
    >>>(int *)(char *)&v != &v

    >>
    >> Guaranteed to work (evaluating to 0) if `v' is an `int'.
    >>
    >> Potential undefined behavior if `v' is not an `int': the
    >>conversion of any arbitrary (object) pointer to `char*' is
    >>well-defined, but even so this does not justify the subsequent
    >>attempt to convert a non-`int*' to an `int*'. There are a few
    >>cases is which this is guaranteed to work (e.g., if `v' is a
    >>struct whose first element is an `int'), but in general the
    >>conversion is not safe.

    >
    >
    > Am I correct in thinking that conversion of a T* to a char* is always
    > safe (because sizeof char <= sizeof T for all types T) but the other way
    > round may not be? For instance, an int* might be constrained to have
    > some bits zero, so conversion to an int* with those bits set might
    > either cause a hardware exception or 'silently' set the bits to zero.


    Converting `AnyData*' to `char*' (and back) is always safe,
    but it's because the Standard says so, not because of the `sizeof'
    relation. The Standard does not sanction the conversion of
    `int*' to `short*', even when sizeof(short)<=sizeof(int). (I've
    never encountered a system where this relation didn't hold or
    where the conversion wouldn't work, but "There are more things
    on Heaven and Earth" and my experience is non-infinite ...)

    --
    Eric Sosman
    lid
    Eric Sosman, Jan 12, 2005
    #18
  19. x-pander

    Michael Mair Guest

    Lawrence Kirby wrote:
    > On Wed, 12 Jan 2005 12:45:59 +0100, Michael Mair wrote:
    >
    >
    >>Lawrence Kirby wrote:
    >>
    >>[snip: void * vs char *]
    >>
    >>
    >>>Yes, void * uses the same representation as pointers to character types.

    >>
    >>Are you sure of that? It is IMO logical but not necessary.

    >
    >
    > 6.2.5 says
    >
    > "A pointer to void shall have the same representation and alignment
    > requirements as a pointer to a character type."


    Thanks to you and pete :)


    >>I am not sure where but a couple of months ago there was a discussion
    >>where the example function execl() from the FAQ 5.2 (
    >>http://www.eskimo.com/~scs/C-faq/q5.2.html ) was cited and where some
    >>regulars stressed how important the cast (char *) is because execl is a
    >>function with variable argument list and so we need to make sure that we
    >>get (char *) NULL instead of plain (that is, (void *)) NULL.

    >
    >
    > The case is important because NULL can be defined as, say, 0 i.e. have
    > an integer type. This is certainly not guaranteed in any sense to have any
    > representational equivalence to a pointer.
    >
    > There is a footnote for the standard text above that says:
    >
    > "The same representation and alignment requirements are meant to imply
    > interchangeability as arguments to functions, return values from
    > functions, and members of unions."
    >
    > which brings up the question of whether you are guaranteed to be able to
    > pass a void * argument to a function that requires a char *. As the text
    > suggests you are pretty safe in doing this. OTOH the footnote is not
    > normative and the text of the standard makes no absolute guarantee.


    Essentially, this makes void * a pointer to a character type but
    for pointer arithmetics.
    For the above mentioned execl() call I could also use a terminating
    "(void *) 0" and be on the safe side.


    Thank you for clarifying
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
    Michael Mair, Jan 12, 2005
    #19
  20. x-pander

    CBFalconer Guest

    Lawrence Kirby wrote:
    >

    .... snip ...
    >
    > which brings up the question of whether you are guaranteed to be
    > able to pass a void * argument to a function that requires a char *.
    > As the text suggests you are pretty safe in doing this. OTOH the
    > footnote is not normative and the text of the standard makes no
    > absolute guarantee.


    You can pass a void* to a function requiring any form of pointer,
    and the conversion is automatic. That is one of the points of
    having the void* type.

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
    CBFalconer, Jan 12, 2005
    #20
    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. Gopi

    point to point protocol

    Gopi, Jul 13, 2004, in forum: VHDL
    Replies:
    1
    Views:
    461
    Mike Treseler
    Jul 13, 2004
  2. H aka N
    Replies:
    15
    Views:
    15,613
    Ben Jones
    Mar 2, 2006
  3. Motaz Saad
    Replies:
    7
    Views:
    6,458
  4. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    655
  5. Saraswati lakki
    Replies:
    0
    Views:
    1,288
    Saraswati lakki
    Jan 6, 2012
Loading...

Share This Page