pointer conversion

Discussion in 'C Programming' started by junky_fellow@yahoo.co.in, Aug 31, 2007.

  1. Guest

    guys,

    I have a question regarding pointer conversion. Please look at the
    following code snippet.

    char *cptr;
    int *iptr;

    /* Some code here that initializes "iptr" */

    cptr = (char *)iptr; /* Line 1
    */
    cptr = cptr + sizeof(int); /* Line 2 */
    iptr = (int *)cptr; /* Line 3 */

    Now as per the pointer conversion rule:
    Page 47: n1124.pdf

    A pointer to an object or incomplete type may be converted to a
    pointer to a different object or incomplete type. If the resulting
    pointer is not correctly aligned57) for thepointed-to type, the
    behavior is undefined. Otherwise, when converted back again, the
    result shall compare equal to the original pointer.

    According to above conversion rule, "Line 1" should be perfectly fine.
    But, I want to know if the conversion done at "Line 3" is allowed or
    not.
    I have this doubt because the "cptr" has been changed.
    But, it is properly aligned to point to an integer object.
    , Aug 31, 2007
    #1
    1. Advertising

  2. <> wrote in message
    news:...
    > guys,
    >
    > I have a question regarding pointer conversion. Please look at the
    > following code snippet.
    >
    > char *cptr;
    > int *iptr;
    >
    > /* Some code here that initializes "iptr" */
    >
    > cptr = (char *)iptr; /* Line 1
    > */
    > cptr = cptr + sizeof(int); /* Line 2 */
    > iptr = (int *)cptr; /* Line 3 */
    >
    > Now as per the pointer conversion rule:
    > Page 47: n1124.pdf
    >
    > A pointer to an object or incomplete type may be converted to a
    > pointer to a different object or incomplete type. If the resulting
    > pointer is not correctly aligned57) for thepointed-to type, the
    > behavior is undefined. Otherwise, when converted back again, the
    > result shall compare equal to the original pointer.
    >
    > According to above conversion rule, "Line 1" should be perfectly fine.
    > But, I want to know if the conversion done at "Line 3" is allowed or
    > not.
    > I have this doubt because the "cptr" has been changed.
    > But, it is properly aligned to point to an integer object.
    >

    You will be OK.
    char is always 1 byte. So casting an arbitrary pointer to a char *, adding
    an exact multiple of the size of the original type, and casting back is
    guaranteed to preserve alignment.

    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
    Malcolm McLean, Aug 31, 2007
    #2
    1. Advertising

  3. >>>>> "M" == Malcolm McLean <> writes:

    M> You will be OK. char is always 1 byte. So casting an arbitrary
    M> pointer to a char *, adding an exact multiple of the size of
    M> the original type, and casting back is guaranteed to preserve
    M> alignment.

    I am not so sure about that; would you care to cite C&V, please, if
    you claim that it's guaranteed by the standard?

    Charlton


    --
    Charlton Wilbur
    Charlton Wilbur, Aug 31, 2007
    #3
  4. "Charlton Wilbur" <> wrote in message
    news:...
    >>>>>> "M" == Malcolm McLean <> writes:

    >
    > M> You will be OK. char is always 1 byte. So casting an arbitrary
    > M> pointer to a char *, adding an exact multiple of the size of
    > M> the original type, and casting back is guaranteed to preserve
    > M> alignment.
    >
    > I am not so sure about that; would you care to cite C&V, please, if
    > you claim that it's guaranteed by the standard?
    >

    Arrays have to be contiguous in memory. No padding bytes may be inserted
    between items.
    The rest follows from that.

    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
    Malcolm McLean, Aug 31, 2007
    #4
  5. In article <>,
    Eric Sosman <> wrote:

    >> M> You will be OK. char is always 1 byte. So casting an arbitrary
    >> M> pointer to a char *, adding an exact multiple of the size of
    >> M> the original type, and casting back is guaranteed to preserve
    >> M> alignment.


    >> I am not so sure about that; would you care to cite C&V, please, if
    >> you claim that it's guaranteed by the standard?


    > He's wrong: it's not guaranteed. Simple example:
    >
    > int target = 42;
    > int *ptr = &target + 1; /* "an arbitrary pointer" */
    > ptr = (int*)((char*)ptr + sizeof *ptr); /* U.B. */
    >
    > If the original pointer points at an actual object of its
    >type (so it's not "arbitrary"), the conversion is safe.


    That seems to be excessive pedantry. He said it "preserves
    alignment", not that it's legal. Presumably you would deny that
    adding 2 to an int preserves it odd/even parity, because you might
    choose INT_MAX.

    -- Richard

    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
    Richard Tobin, Aug 31, 2007
    #5
  6. Eric Sosman Guest

    Charlton Wilbur wrote:
    >>>>>> "M" == Malcolm McLean <> writes:

    >
    > M> You will be OK. char is always 1 byte. So casting an arbitrary
    > M> pointer to a char *, adding an exact multiple of the size of
    > M> the original type, and casting back is guaranteed to preserve
    > M> alignment.
    >
    > I am not so sure about that; would you care to cite C&V, please, if
    > you claim that it's guaranteed by the standard?


    He's wrong: it's not guaranteed. Simple example:

    int target = 42;
    int *ptr = &target + 1; /* "an arbitrary pointer" */
    ptr = (int*)((char*)ptr + sizeof *ptr); /* U.B. */

    If the original pointer points at an actual object of its
    type (so it's not "arbitrary"), the conversion is safe.

    --
    Eric Sosman
    lid
    Eric Sosman, Aug 31, 2007
    #6
  7. CBFalconer Guest

    Malcolm McLean wrote:
    >

    .... snip ...
    >
    > Arrays have to be contiguous in memory. No padding bytes may be
    > inserted between items. The rest follows from that.


    Nonsense. Consider:

    struct foo {int iv; char ch} arr[N];

    A struct foo, on a machine with sizeof int == 4, will be occupy 5
    bytes. However, in order to make addressable arrays of these,
    sizeof struct foo == 8 (assuming ints need to be aligned modulo
    4). I.E. there are 3 padding bytes per item.

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>



    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Aug 31, 2007
    #7
  8. "Richard Tobin" <> wrote in message
    news:fb9ran$1fap$...
    > In article <>,
    > Eric Sosman <> wrote:
    >
    >>> M> You will be OK. char is always 1 byte. So casting an arbitrary
    >>> M> pointer to a char *, adding an exact multiple of the size of
    >>> M> the original type, and casting back is guaranteed to preserve
    >>> M> alignment.

    >
    >>> I am not so sure about that; would you care to cite C&V, please, if
    >>> you claim that it's guaranteed by the standard?

    >
    >> He's wrong: it's not guaranteed. Simple example:
    >>
    >> int target = 42;
    >> int *ptr = &target + 1; /* "an arbitrary pointer" */
    >> ptr = (int*)((char*)ptr + sizeof *ptr); /* U.B. */
    >>
    >> If the original pointer points at an actual object of its
    >>type (so it's not "arbitrary"), the conversion is safe.

    >
    > That seems to be excessive pedantry. He said it "preserves
    > alignment", not that it's legal. Presumably you would deny that
    > adding 2 to an int preserves it odd/even parity, because you might
    > choose INT_MAX.
    >

    Yes, to be a successful pedant you've got to be absolutely, precisely
    accurate.

    Clearly if the pointer is misaligned, adding sizeof(*ptr) will preserve the
    (mis) alignment.

    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
    Malcolm McLean, Aug 31, 2007
    #8
  9. Eric Sosman Guest

    Richard Tobin wrote:
    > In article <>,
    > Eric Sosman <> wrote:
    >
    >>> M> You will be OK. char is always 1 byte. So casting an arbitrary
    >>> M> pointer to a char *, adding an exact multiple of the size of
    >>> M> the original type, and casting back is guaranteed to preserve
    >>> M> alignment.

    >
    >>> I am not so sure about that; would you care to cite C&V, please, if
    >>> you claim that it's guaranteed by the standard?

    >
    >> He's wrong: it's not guaranteed. Simple example:
    >>
    >> int target = 42;
    >> int *ptr = &target + 1; /* "an arbitrary pointer" */
    >> ptr = (int*)((char*)ptr + sizeof *ptr); /* U.B. */
    >>
    >> If the original pointer points at an actual object of its
    >> type (so it's not "arbitrary"), the conversion is safe.

    >
    > That seems to be excessive pedantry. He said it "preserves
    > alignment", not that it's legal. Presumably you would deny that
    > adding 2 to an int preserves it odd/even parity, because you might
    > choose INT_MAX.


    Adding two to an "arbitrary" integer need not preserve
    parity, although adding two to most integers does. For the
    two problematic integers you get undefined behavior, after
    which assertions about what is and isn't preserved -- or
    pickled -- just evaporate.

    Adding sizeof *ptr to an "arbitrary" value of ptr need
    not preserve alignment, although adding it to a restricted
    class of values certainly does. But once U.B. occurs, the
    Standard abdicates and no longer supports arguments that
    formerly relied on it. It is wrong to claim that alignment
    preservation is "guaranteed" in light of U.B.; "guaranteed"
    by whom or by what?

    BTW, "excessive pedantry" is unnecessarily redundant. ;-)

    --
    Eric Sosman
    lid
    Eric Sosman, Aug 31, 2007
    #9
  10. In article <>,
    Malcolm McLean <> wrote:

    >Yes, to be a successful pedant you've got to be absolutely, precisely
    >accurate.
    >
    >Clearly if the pointer is misaligned, adding sizeof(*ptr) will preserve the
    >(mis) alignment.


    No. If you're a real pedant, you will observe that the undefined
    behaviour of creating the misaligned pointer could be that the addition
    produces an aligned one.

    But the example wasn't a misaligned pointer - it was that the addition
    produced a pointer outside of the object.

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
    Richard Tobin, Aug 31, 2007
    #10
  11. In article <>,
    Eric Sosman <> wrote:

    > BTW, "excessive pedantry" is unnecessarily redundant. ;-)


    I thought the comp.lang.c view was that it's an oxymoron.

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
    Richard Tobin, Aug 31, 2007
    #11
  12. "Richard Tobin" <> wrote in message
    news:fb9ura$1g6t$...
    > In article <>,
    > Malcolm McLean <> wrote:
    >
    >>Yes, to be a successful pedant you've got to be absolutely, precisely
    >>accurate.
    >>
    >>Clearly if the pointer is misaligned, adding sizeof(*ptr) will preserve
    >>the
    >>(mis) alignment.

    >
    > No. If you're a real pedant, you will observe that the undefined
    > behaviour of creating the misaligned pointer could be that the addition
    > produces an aligned one.
    >

    I surrender. Yes, the misaligned pointer can only be assigned to a pointer
    of that type with UB, after which any futher operations are allowed to
    produce any results whatsoever.
    >
    > But the example wasn't a misaligned pointer - it was that the addition
    > produced a pointer outside of the object.
    >

    That's an example of useful pedantry. I should have specified that the
    operation is not safe, if the new pointer cannot be contained in the old
    object.

    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
    Malcolm McLean, Aug 31, 2007
    #12
  13. In article <>,
    CBFalconer <> wrote:

    >> Arrays have to be contiguous in memory. No padding bytes may be
    >> inserted between items. The rest follows from that.


    >Nonsense. Consider:
    >
    > struct foo {int iv; char ch} arr[N];
    >
    >A struct foo, on a machine with sizeof int == 4, will be occupy 5
    >bytes. However, in order to make addressable arrays of these,
    >sizeof struct foo == 8 (assuming ints need to be aligned modulo
    >4). I.E. there are 3 padding bytes per item.


    But these padding bytes are part of the items, not between them.
    sizeof(struct foo) has to be 8 regardless of whether the struct is in
    an array. If it's in another struct, the 3 padding bytes have to be
    there even if the next item in the struct is a char. Even if it's
    just a plain automatic variable, the bytes have to be present and
    not used for another object, because you could memcpy() 8 bytes
    to it.

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
    Richard Tobin, Aug 31, 2007
    #13
  14. CBFalconer Guest

    Eric Sosman wrote:
    >

    .... snip ...
    >
    > Adding two to an "arbitrary" integer need not preserve parity,
    > although adding two to most integers does. For the two problematic
    > integers you get undefined behavior, after which assertions about
    > what is and isn't preserved -- or pickled -- just evaporate.


    Oh? When I was in primary school:

    4 had 1 bit
    4 + 2 is 6, with 2 bits
    6 + 2 is 8, with 1 bit

    which doesn't seem to preserve parity.

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>



    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Aug 31, 2007
    #14
  15. CBFalconer <> writes:
    > Malcolm McLean wrote:
    > ... snip ...
    >>
    >> Arrays have to be contiguous in memory. No padding bytes may be
    >> inserted between items. The rest follows from that.

    >
    > Nonsense. Consider:
    >
    > struct foo {int iv; char ch} arr[N];
    >
    > A struct foo, on a machine with sizeof int == 4, will be occupy 5
    > bytes. However, in order to make addressable arrays of these,
    > sizeof struct foo == 8 (assuming ints need to be aligned modulo
    > 4). I.E. there are 3 padding bytes per item.


    No, there are 3 padding bytes *within* each item.

    Assumptions:
    sizeof(int) == 4
    int requires 4-byte alignment.
    The implementation inserts no more padding in structs than is
    necessary to meet alignment requirements.

    Then sizeof(struct foo) == 8, which includes 3 padding bytes (probably
    after ch, but they could be before it or both given a sufficiently
    whimsical compiler).

    There is no padding between elements of an array. In this example,
    each element occupies a full 8 bytes, with no additional padding
    either necessary or permitted.

    I've used languages which do allow padding between array elements. In
    such a language, sizeof(struct foo) might be 5 bytes, but
    sizeof(struct foo[1]) might be 8 bytes. In C, though, a single object
    of type struct foo must occupy 8 bytes, whether it's an array element
    or not. (Actually, any single object is effectively an array
    element.)

    --
    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."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Aug 31, 2007
    #15
  16. In article <>,
    CBFalconer <> wrote:

    >Oh? When I was in primary school:
    >
    > 4 had 1 bit
    > 4 + 2 is 6, with 2 bits
    > 6 + 2 is 8, with 1 bit
    >
    >which doesn't seem to preserve parity.


    Oops. I was using the term "parity" in the mathematical sense of
    whether a number is odd or even; not in the computer sense of whether
    it has an odd or even number of bits set. I used the phrase "odd/even
    parity" to emphasize the kind of parity I meant, but of course it does
    nothing of the kind.

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
    Richard Tobin, Aug 31, 2007
    #16
  17. CBFalconer Guest

    Richard Tobin wrote:
    > CBFalconer <> wrote:
    >
    >>> Arrays have to be contiguous in memory. No padding bytes may be
    >>> inserted between items. The rest follows from that.

    >
    >> Nonsense. Consider:
    >>
    >> struct foo {int iv; char ch} arr[N];
    >>
    >> A struct foo, on a machine with sizeof int == 4, will be occupy 5
    >> bytes. However, in order to make addressable arrays of these,
    >> sizeof struct foo == 8 (assuming ints need to be aligned modulo
    >> 4). I.E. there are 3 padding bytes per item.

    >
    > But these padding bytes are part of the items, not between them.
    > sizeof(struct foo) has to be 8 regardless of whether the struct is in
    > an array. If it's in another struct, the 3 padding bytes have to be
    > there even if the next item in the struct is a char. Even if it's
    > just a plain automatic variable, the bytes have to be present and
    > not used for another object, because you could memcpy() 8 bytes
    > to it.


    If you think about it for about 2 1/4 secs I am sure you can come
    up with a struct definition that puts the padding in the middle.
    Don't forget that ALL items have to be aligned.

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>


    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Aug 31, 2007
    #17
  18. CBFalconer <> writes:
    > Richard Tobin wrote:
    >> CBFalconer <> wrote:
    >>
    >>>> Arrays have to be contiguous in memory. No padding bytes may be
    >>>> inserted between items. The rest follows from that.

    >>
    >>> Nonsense. Consider:
    >>>
    >>> struct foo {int iv; char ch} arr[N];
    >>>
    >>> A struct foo, on a machine with sizeof int == 4, will be occupy 5
    >>> bytes. However, in order to make addressable arrays of these,
    >>> sizeof struct foo == 8 (assuming ints need to be aligned modulo
    >>> 4). I.E. there are 3 padding bytes per item.

    >>
    >> But these padding bytes are part of the items, not between them.
    >> sizeof(struct foo) has to be 8 regardless of whether the struct is in
    >> an array. If it's in another struct, the 3 padding bytes have to be
    >> there even if the next item in the struct is a char. Even if it's
    >> just a plain automatic variable, the bytes have to be present and
    >> not used for another object, because you could memcpy() 8 bytes
    >> to it.

    >
    > If you think about it for about 2 1/4 secs I am sure you can come
    > up with a struct definition that puts the padding in the middle.
    > Don't forget that ALL items have to be aligned.


    So what? The point is that padding may be inserted between members of
    a struct, but padding *may not* be inserted between elements of an
    array.

    Any padding in struct foo, whether it's between members, after the
    last member, or both, is *part of struct foo*.

    Given
    struct foo arr[N];
    any padding between arr[0] and arr[1] is guaranteed to be nonexistent.

    If this weren't the case, then the common idiom
    sizeof arr / sizeof arr[0]
    to determine the length of an array would not work.

    The statement that you disputed, quoted above, was

    Arrays have to be contiguous in memory. No padding bytes may be
    inserted between items. The rest follows from that.

    That statement was perfectly correct.

    --
    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."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Sep 1, 2007
    #18
  19. On 31 Aug 2007 12:24:43 -0400, Charlton Wilbur
    <> wrote:

    >>>>>> "M" == Malcolm McLean <> writes:

    >
    > M> You will be OK. char is always 1 byte. So casting an arbitrary
    > M> pointer to a char *, adding an exact multiple of the size of
    > M> the original type, and casting back is guaranteed to preserve
    > M> alignment.
    >
    >I am not so sure about that; would you care to cite C&V, please, if
    >you claim that it's guaranteed by the standard?
    >


    It follows directly from paragraph 2 in section 6.5.2.1 and the first
    few sentences of paragraph 8 in section 6.5.6 of n1124.

    While the arithmetic is guaranteed to preserve alignment, it can still
    invoke undefined behavior. If the resulting address is not within (or
    just 1 past the end of) the original object, the next to last sentence
    of paragraph 8 of section 6.5.6 applies.


    Remove del for email
    Barry Schwarz, Sep 1, 2007
    #19
  20. CBFalconer Guest

    Keith Thompson wrote:
    > CBFalconer <> writes:
    >> Richard Tobin wrote:
    >>> CBFalconer <> wrote:
    >>>
    >>>>> Arrays have to be contiguous in memory. No padding bytes may be
    >>>>> inserted between items. The rest follows from that.
    >>>
    >>>> Nonsense. Consider:
    >>>>
    >>>> struct foo {int iv; char ch} arr[N];
    >>>>
    >>>> A struct foo, on a machine with sizeof int == 4, will be occupy 5
    >>>> bytes. However, in order to make addressable arrays of these,
    >>>> sizeof struct foo == 8 (assuming ints need to be aligned modulo
    >>>> 4). I.E. there are 3 padding bytes per item.
    >>>
    >>> But these padding bytes are part of the items, not between them.
    >>> sizeof(struct foo) has to be 8 regardless of whether the struct is in
    >>> an array. If it's in another struct, the 3 padding bytes have to be
    >>> there even if the next item in the struct is a char. Even if it's
    >>> just a plain automatic variable, the bytes have to be present and
    >>> not used for another object, because you could memcpy() 8 bytes
    >>> to it.

    >>
    >> If you think about it for about 2 1/4 secs I am sure you can come
    >> up with a struct definition that puts the padding in the middle.
    >> Don't forget that ALL items have to be aligned.

    >
    > So what? The point is that padding may be inserted between members of
    > a struct, but padding *may not* be inserted between elements of an
    > array.
    >
    > Any padding in struct foo, whether it's between members, after the
    > last member, or both, is *part of struct foo*.
    >
    > Given
    > struct foo arr[N];
    > any padding between arr[0] and arr[1] is guaranteed to be nonexistent.
    >
    > If this weren't the case, then the common idiom
    > sizeof arr / sizeof arr[0]
    > to determine the length of an array would not work.
    >
    > The statement that you disputed, quoted above, was
    >
    > Arrays have to be contiguous in memory. No padding bytes may be
    > inserted between items. The rest follows from that.
    >
    > That statement was perfectly correct.


    No, because you are considering the structure to be a monolith,
    while I am looking at it as consisting of some sort of combination
    of items, possibly separated by padding. If your quoted line said
    "between array items" I would have to agree.

    It really is counting angels on pinheads, and not important.
    Meanwhile we amuse ourselves.

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>


    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Sep 1, 2007
    #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. pw4getter

    pointer to pointer conversion

    pw4getter, Mar 5, 2004, in forum: C++
    Replies:
    5
    Views:
    3,650
    Casey Carter
    Mar 5, 2004
  2. Replies:
    10
    Views:
    698
    Chris Torek
    Feb 4, 2005
  3. jimjim
    Replies:
    16
    Views:
    838
    Jordan Abel
    Mar 28, 2006
  4. WaterWalk

    Pointer to pointer conversion

    WaterWalk, May 22, 2008, in forum: C Programming
    Replies:
    3
    Views:
    324
    WaterWalk
    May 23, 2008
  5. Replies:
    4
    Views:
    1,253
    Fred Zwarts
    Jul 2, 2009
Loading...

Share This Page