Pointer to inside an array

Discussion in 'C Programming' started by Alok Singhal, Dec 15, 2009.

  1. Alok  Singhal

    Alok Singhal Guest

    Hi,

    Let's say I have:

    int a[20] = {0};

    Is the declaration below legal according to C89?

    int (*p)[5] = (int (*)[5])(a+6);
    Alok Singhal, Dec 15, 2009
    #1
    1. Advertising

  2. Alok  Singhal

    mohangupta13 Guest

    On Dec 15, 4:03 pm, Alok Singhal <> wrote:
    > Hi,
    >
    > Let's say I have:
    >
    > int a[20] = {0};
    >
    > Is the declaration below legal according to C89?
    >
    > int (*p)[5] = (int (*)[5])(a+6);

    As far as i think (i am not 100% certain though) its legal. But in
    this case only (p+2)[3] can be safely addressed for storing values.

    Mohan
    mohangupta13, Dec 15, 2009
    #2
    1. Advertising

  3. Alok  Singhal

    annalissa Guest

    On Dec 15, 12:24 pm, mohangupta13 <> wrote:
    > On Dec 15, 4:03 pm, Alok  Singhal <> wrote:> Hi,
    >
    > > Let's say I have:

    >
    > > int a[20] = {0};

    >
    > > Is the declaration below legal according to C89?

    >
    > > int (*p)[5] = (int (*)[5])(a+6);


    consider this program:-

    #include<stdio.h>
    #include<stdlib.h>

    int main(void)
    {

    int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};

    int (*p)[5] = (int(*)[5])(a+6);

    printf("\n %d",(*p)[0]);

    return(EXIT_SUCCESS);
    }

    compile this program as gcc -g -ansi -pedantic -o progname
    progname.c , then decide for yourself



    > As far as i think (i am not 100% certain though) its legal. But in
    > this case only (p+2)[3] can be safely addressed for storing values.


    what do you mean by the statement that (p+2)[3] can be safely
    addressed for storing values. ???
    annalissa, Dec 15, 2009
    #3
  4. Alok  Singhal

    mohangupta13 Guest

    On Dec 16, 12:25 am, annalissa <> wrote:
    > On Dec 15, 12:24 pm, mohangupta13 <> wrote:
    >
    > > On Dec 15, 4:03 pm, Alok  Singhal <> wrote:> Hi,

    >
    > > > Let's say I have:

    >
    > > > int a[20] = {0};

    >
    > > > Is the declaration below legal according to C89?

    >
    > > > int (*p)[5] = (int (*)[5])(a+6);

    >
    > consider this program:-
    >
    > #include<stdio.h>
    > #include<stdlib.h>
    >
    > int main(void)
    > {
    >
    >  int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
    >
    >   int (*p)[5] = (int(*)[5])(a+6);
    >
    >   printf("\n %d",(*p)[0]);
    >
    >   return(EXIT_SUCCESS);
    >
    > }
    >
    > compile this program as gcc -g -ansi -pedantic -o progname
    > progname.c , then decide for yourself
    >
    > > As far as i think (i am not 100% certain though) its legal. But in
    > > this case only (p+2)[3] can be safely addressed for storing values.

    >
    > what do you mean by the statement that (p+2)[3] can be safely
    > addressed for storing values. ???


    well i meant that the last value accessible through p is (p+2)[3] it
    should be the value at a[19].
    mohangupta13, Dec 15, 2009
    #4
  5. Alok  Singhal

    Alok Singhal Guest

    On Tue, 15 Dec 2009 11:25:14 -0800, annalissa wrote:
    > consider this program:-
    >
    > #include<stdio.h>
    > #include<stdlib.h>
    >
    > int main(void)
    > {
    >
    > int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
    >
    > int (*p)[5] = (int(*)[5])(a+6);
    >
    > printf("\n %d",(*p)[0]);
    >
    > return(EXIT_SUCCESS);
    > }
    >
    > compile this program as gcc -g -ansi -pedantic -o progname progname.c ,
    > then decide for yourself


    Yes, gcc doesn't give any warnings, but we are casting p to what we
    want. If we remove the cast, gcc does give a warning saying:
    "initialization from incompatible pointer type". I understand that the
    initialization is from an incompatible pointer type, so I *think* this
    means that the behavior is undefined. But I am not sure.

    Thanks,
    Alok
    Alok Singhal, Dec 15, 2009
    #5
  6. mohangupta13 <> writes:

    > On Dec 16, 12:25 am, annalissa <> wrote:
    >> On Dec 15, 12:24 pm, mohangupta13 <> wrote:
    >>
    >> > On Dec 15, 4:03 pm, Alok  Singhal <> wrote:> Hi,

    >>
    >> > > Let's say I have:

    >>
    >> > > int a[20] = {0};

    >>
    >> > > Is the declaration below legal according to C89?

    >>
    >> > > int (*p)[5] = (int (*)[5])(a+6);

    <snip>
    >> > As far as i think (i am not 100% certain though) its legal.


    "Legal" is an odd word in this context. The conversion between the
    two pointer types is implementation defined so I suppose pretty much
    any result is possible though there is an "obvious" conversion.

    >> > But in
    >> > this case only (p+2)[3] can be safely addressed for storing values.

    >>
    >> what do you mean by the statement that (p+2)[3] can be safely
    >> addressed for storing values. ???

    >
    > well i meant that the last value accessible through p is (p+2)[3] it
    > should be the value at a[19].


    (p+2)[3] and a[19] have different types. You probably meant
    (*(p+2))[3] but that is simpler to right as p[2][3].

    --
    Ben.
    Ben Bacarisse, Dec 15, 2009
    #6
  7. On Tue, 15 Dec 2009 20:06:07 +0000 (UTC), Alok Singhal
    <> wrote:

    >On Tue, 15 Dec 2009 11:25:14 -0800, annalissa wrote:
    >> consider this program:-
    >>
    >> #include<stdio.h>
    >> #include<stdlib.h>
    >>
    >> int main(void)
    >> {
    >>
    >> int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
    >>
    >> int (*p)[5] = (int(*)[5])(a+6);
    >>
    >> printf("\n %d",(*p)[0]);
    >>
    >> return(EXIT_SUCCESS);
    >> }
    >>
    >> compile this program as gcc -g -ansi -pedantic -o progname progname.c ,
    >> then decide for yourself

    >
    >Yes, gcc doesn't give any warnings, but we are casting p to what we
    >want. If we remove the cast, gcc does give a warning saying:
    >"initialization from incompatible pointer type". I understand that the
    >initialization is from an incompatible pointer type, so I *think* this
    >means that the behavior is undefined. But I am not sure.


    Think again. The purpose of the cast is not to silence the warning
    but to coerce the value of the expression to a compatible type and
    eliminate the condition that requires a diagnostic.

    The code
    unsigned char *ptr = (unsigned char*)(a+6);
    will produce the exact same warning without the cast yet the
    initialization is perfectly well defined as written.

    --
    Remove del for email
    Barry Schwarz, Dec 16, 2009
    #7
  8. annalissa <> wrote:
    > mohangupta13 <> wrote:
    > > Alok  Singhal <> wrote:> Hi,
    > > > Let's say I have:
    > > >
    > > > int a[20] = {0};
    > > >
    > > > Is the declaration below legal according to C89?
    > > >
    > > > int (*p)[5] = (int (*)[5])(a+6);


    Depends on wheather a+6 is properly aligned for an int(*)[5].
    If not, then no, it's not valid. I don't believe the standard
    guarantees you can dereference it, only convert it back to an
    int *. Also, you are accessing part of an object using a
    different type to the effective type.

    > consider this program:-

    <snip>
    >
    > compile this program as gcc -g -ansi -pedantic -o progname
    > progname.c , then decide for yourself


    That something compiles without a diagnostic under gcc does not
    mean it is correct. E.g. ...

    int main(void) { return * (int *) 0; }

    --
    Peter
    Peter Nilsson, Dec 16, 2009
    #8
  9. Alok  Singhal

    annalissa Guest

    On Dec 15, 11:00 pm, Peter Nilsson <> wrote:
    > annalissa <> wrote:
    > > mohangupta13 <> wrote:
    > > > Alok  Singhal <> wrote:> Hi,
    > > > > Let's say I have:

    >
    > > > > int a[20] = {0};

    >
    > > > > Is the declaration below legal according to C89?

    >
    > > > > int (*p)[5] = (int (*)[5])(a+6);

    >
    > Depends on wheather a+6 is properly aligned for an int(*)[5].
    > If not, then no, it's not valid. I don't believe the standard
    > guarantees you can dereference it, only convert it back to an
    > int *. Also, you are accessing part of an object using a
    > different type to the effective type.
    >
    >
    >
    > > consider this program:-

    > <snip>
    >
    > > compile this program as gcc -g -ansi -pedantic -o progname
    > > progname.c , then decide for yourself

    >
    > That something compiles without a diagnostic under gcc does not
    > mean it is correct. E.g. ...
    >
    >   int main(void) { return * (int *) 0; }



    what is the diagnostic that i am missing ..??
    annalissa, Dec 16, 2009
    #9
  10. Alok  Singhal

    Alok Singhal Guest

    On Tue, 15 Dec 2009 18:31:44 -0800, Barry Schwarz wrote:
    > On Tue, 15 Dec 2009 20:06:07 +0000 (UTC), Alok Singhal
    > <> wrote:
    >>>
    >>> int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
    >>>
    >>> int (*p)[5] = (int(*)[5])(a+6);

    >
    > Think again. The purpose of the cast is not to silence the warning but
    > to coerce the value of the expression to a compatible type and eliminate
    > the condition that requires a diagnostic.
    >
    > The code
    > unsigned char *ptr = (unsigned char*)(a+6);
    > will produce the exact same warning without the cast yet the
    > initialization is perfectly well defined as written.


    Thanks. This is what I was looking for. I should have read the standard
    more carefully as well. So 6.3.2.3p7 (N1336) applies here:

    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 aligned for the pointed-to type, the behavior
    is undefined. Otherwise, when converted back again, the result shall
    compare equal to the original pointer.

    There is no guarantee that int (*)[5] is correctly aligned for int *, and
    even if it is, the standard makes no guarantees about dereferencing such
    a pointer.

    -Alok
    Alok Singhal, Dec 16, 2009
    #10
  11. On Wed, 16 Dec 2009 17:50:42 +0000 (UTC), Alok Singhal
    <> wrote:

    >On Tue, 15 Dec 2009 18:31:44 -0800, Barry Schwarz wrote:
    >> On Tue, 15 Dec 2009 20:06:07 +0000 (UTC), Alok Singhal
    >> <> wrote:
    >>>>
    >>>> int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
    >>>>
    >>>> int (*p)[5] = (int(*)[5])(a+6);

    >>
    >> Think again. The purpose of the cast is not to silence the warning but
    >> to coerce the value of the expression to a compatible type and eliminate
    >> the condition that requires a diagnostic.
    >>
    >> The code
    >> unsigned char *ptr = (unsigned char*)(a+6);
    >> will produce the exact same warning without the cast yet the
    >> initialization is perfectly well defined as written.

    >
    >Thanks. This is what I was looking for. I should have read the standard
    >more carefully as well. So 6.3.2.3p7 (N1336) applies here:
    >
    > 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 aligned for the pointed-to type, the behavior
    > is undefined. Otherwise, when converted back again, the result shall
    > compare equal to the original pointer.
    >
    >There is no guarantee that int (*)[5] is correctly aligned for int *, and
    >even if it is, the standard makes no guarantees about dereferencing such
    >a pointer.


    Do you just invent these assumptions or do you read them somewhere
    that we can tell others to avoid?

    int array[5] = {2};
    int (*ptr_a)[5] = &array;
    int *ptr_i = array;

    Is there any doubt in your mind that both pointers point to the same
    address in memory? Is there any doubt that the expression
    (unsigned char*)ptr_a == (unsigned char*)ptr_i
    will evaluate to 1.

    Is there any doubt in your mind that ptr_i[0] references the first
    element of the array and evaluates to 2 while ptr_i[1] references the
    second element and evaluates to 0?

    Is there any doubt in your mind ptr_a[0][0] and ptr_a[0][1] reference
    the exact same objects and hence must evaluate to the same values?

    --
    Remove del for email
    Barry Schwarz, Dec 17, 2009
    #11
  12. On Wed, 16 Dec 2009 09:27:28 -0800 (PST), annalissa
    <> wrote:

    >On Dec 15, 11:00 pm, Peter Nilsson <> wrote:
    >> annalissa <> wrote:
    >> > mohangupta13 <> wrote:
    >> > > Alok  Singhal <> wrote:> Hi,
    >> > > > Let's say I have:

    >>
    >> > > > int a[20] = {0};

    >>
    >> > > > Is the declaration below legal according to C89?

    >>
    >> > > > int (*p)[5] = (int (*)[5])(a+6);

    >>
    >> Depends on wheather a+6 is properly aligned for an int(*)[5].
    >> If not, then no, it's not valid. I don't believe the standard
    >> guarantees you can dereference it, only convert it back to an
    >> int *. Also, you are accessing part of an object using a
    >> different type to the effective type.
    >>
    >>
    >>
    >> > consider this program:-

    >> <snip>
    >>
    >> > compile this program as gcc -g -ansi -pedantic -o progname
    >> > progname.c , then decide for yourself

    >>
    >> That something compiles without a diagnostic under gcc does not
    >> mean it is correct. E.g. ...
    >>
    >>   int main(void) { return * (int *) 0; }

    >
    >
    >what is the diagnostic that i am missing ..??


    There is no diagnostic required but the code invokes undefined
    behavior.

    --
    Remove del for email
    Barry Schwarz, Dec 17, 2009
    #12
  13. Alok  Singhal

    Alok Singhal Guest

    On Wed, 16 Dec 2009 21:47:47 -0800, Barry Schwarz wrote:
    > On Wed, 16 Dec 2009 17:50:42 +0000 (UTC), Alok Singhal
    > <> wrote:


    <snip>

    >>Thanks. This is what I was looking for. I should have read the
    >>standard more carefully as well. So 6.3.2.3p7 (N1336) applies here:
    >>
    >> 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 aligned for the pointed-to type, the behavior
    >> is undefined. Otherwise, when converted back again, the result shall
    >> compare equal to the original pointer.
    >>
    >>There is no guarantee that int (*)[5] is correctly aligned for int *,
    >>and even if it is, the standard makes no guarantees about dereferencing
    >>such a pointer.

    >
    > Do you just invent these assumptions or do you read them somewhere that
    > we can tell others to avoid?


    Please bear with me while I try to explain myself. Isn't there a
    difference between:

    int array[5] = {2};
    int (*ptr)[5] = &array;

    and:

    int array[20] = {2};
    int (*ptr)[5] = (int (*)[5])(array + 6);

    In the second snippet, "array + 6" is of type "pointer to int". In the
    first snippet, "&array" is of type "int (*)[5]". So, if I understand
    correctly, and I think that is what you're saying too: the first snippet
    is well-defined by the standard, while the result second snippet, in
    particular the assignment to "ptr" is implementation-defined.

    So, *if I understand correctly*, in the second snippet above:

    - the cast is needed because it coerces "a+6" to the correct type for
    "ptr".
    - if "ptr" is a pointer to (signed or unsigned) char, or any other type
    that is correctly aligned for the type of "a+6" (int *), the
    initialization is well-defined in that I can convert "ptr" back to
    int * and get the same value.
    - if "ptr" isn't correctly aligned for int *, the result of the
    initialization is implementation-defined.

    Please let me know where I am wrong in my assumptions.

    > int array[5] = {2};
    > int (*ptr_a)[5] = &array;
    > int *ptr_i = array;
    >
    > Is there any doubt in your mind that both pointers point to the same
    > address in memory? Is there any doubt that the expression
    > (unsigned char*)ptr_a == (unsigned char*)ptr_i
    > will evaluate to 1.
    >
    > Is there any doubt in your mind that ptr_i[0] references the first
    > element of the array and evaluates to 2 while ptr_i[1] references the
    > second element and evaluates to 0?
    >
    > Is there any doubt in your mind ptr_a[0][0] and ptr_a[0][1] reference
    > the exact same objects and hence must evaluate to the same values?


    The answer to all the above questions is, "no". I agree with all the
    statements above.

    Thanks again for your help,
    -Alok
    Alok Singhal, Dec 17, 2009
    #13
  14. On Thu, 17 Dec 2009 17:54:54 +0000 (UTC), Alok Singhal
    <> wrote:

    >On Wed, 16 Dec 2009 21:47:47 -0800, Barry Schwarz wrote:
    >> On Wed, 16 Dec 2009 17:50:42 +0000 (UTC), Alok Singhal
    >> <> wrote:

    >
    ><snip>
    >
    >>>Thanks. This is what I was looking for. I should have read the
    >>>standard more carefully as well. So 6.3.2.3p7 (N1336) applies here:
    >>>
    >>> 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 aligned for the pointed-to type, the behavior
    >>> is undefined. Otherwise, when converted back again, the result shall
    >>> compare equal to the original pointer.
    >>>
    >>>There is no guarantee that int (*)[5] is correctly aligned for int *,
    >>>and even if it is, the standard makes no guarantees about dereferencing
    >>>such a pointer.

    >>
    >> Do you just invent these assumptions or do you read them somewhere that
    >> we can tell others to avoid?

    >
    >Please bear with me while I try to explain myself. Isn't there a
    >difference between:
    >
    > int array[5] = {2};
    > int (*ptr)[5] = &array;
    >
    >and:
    >
    > int array[20] = {2};
    > int (*ptr)[5] = (int (*)[5])(array + 6);
    >
    >In the second snippet, "array + 6" is of type "pointer to int". In the
    >first snippet, "&array" is of type "int (*)[5]". So, if I understand
    >correctly, and I think that is what you're saying too: the first snippet
    >is well-defined by the standard, while the result second snippet, in
    >particular the assignment to "ptr" is implementation-defined.
    >
    >So, *if I understand correctly*, in the second snippet above:
    >
    >- the cast is needed because it coerces "a+6" to the correct type for
    > "ptr".
    >- if "ptr" is a pointer to (signed or unsigned) char, or any other type
    > that is correctly aligned for the type of "a+6" (int *), the
    > initialization is well-defined in that I can convert "ptr" back to
    > int * and get the same value.
    >- if "ptr" isn't correctly aligned for int *, the result of the
    > initialization is implementation-defined.


    If the value a+6 is correctly aligned for the type int(*)[5], then
    your initialization of ptr is well defined. If not, the
    initialization invokes undefined behavior (6.3.2.3-7), not
    implementation defined behavior. So the question revolves around
    whether a+6 is properly aligned.

    Consider the definition
    int x[sizeof(int)][5];

    We know that each element x[j] occupies exactly sizeof(int) bytes.
    Further more, each element x[j+1] starts exactly sizeof(int) bytes
    beyond the start of the previous element x[j] (except for the
    obvious boundary condition when j==4).

    We also know that each x is an array of 5 int and that x[i+1]
    starts exactly 5*sizeof(int) bytes beyond the start of x (again
    except for the boundary condition when i==sizeof(int)-1).

    Because sizeof(int) is not a factor of 5, I assert the x as a group
    completely exhaust all possible alignments for int[5] and that they
    also completely exhaust all possible alignments for int. (I don't
    remember what the branch of mathematics is called that is used to
    prove these assertions but if you choose both common (2, 4, and 8) and
    off-the-wall (3, 15 23) values for sizeof(int) and work out the
    addresses you should be convinced.) Consequently, the value a+6 will
    exactly match the alignment of at least one of the x and is
    therefore properly aligned.

    >
    >Please let me know where I am wrong in my assumptions.
    >


    --
    Remove del for email
    Barry Schwarz, Dec 18, 2009
    #14
  15. Barry Schwarz <> wrote:
    > Alok Singhal
    > > Please bear with me while I try to explain myself. Isn't
    > > there a difference between:
    > >
    > > int array[5] = {2};
    > > int (*ptr)[5] = &array;
    > >
    > > and:
    > >
    > > int array[20] = {2};
    > > int (*ptr)[5] = (int (*)[5])(array + 6);

    >
    > ...the question revolves around whether a+6 is properly aligned.
    >
    > Consider the definition
    > int x[sizeof(int)][5];


    I have no idea why you think sizeof(int) should be used here!

    > We know that each element x[j] occupies exactly sizeof(int)
    > bytes. Further more, each element x[j+1] starts exactly
    > sizeof(int) bytes beyond the start of the previous element
    > x[j] (except for the obvious boundary condition when j==4).
    >
    > We also know that each x is an array of 5 int and that
    > x[i+1] starts exactly 5*sizeof(int) bytes beyond the start
    > of x (again except for the boundary condition when i==
    > sizeof(int)-1).
    >
    > Because sizeof(int) is not a factor of 5,


    Not commonly, but on the virtual machine it may be.

    > I assert the x as a group completely exhaust all possible
    > alignments for int[5] and that they also completely exhaust
    > all possible alignments for int. ...


    I've had a previous discussion considering something like...

    int a[7];
    int (*p)[2] = (int (*)[2]) (a + 1);

    The problem is whether int(*)[2] can have a stricter
    alignement than int *. I think it can! I can't see anything
    in the standard that says a pointer to an element of an array
    of N elements will always be properly aligned for a pointer
    to an array of M elements if M < N.

    Why should it? Look at an example using structs...

    struct int_pair_t { int a; int b; };
    int a[7];
    struct int_pair_t *p = (struct int_pair_t *) (a + 1);

    Even if one shows that there is no padding in the struct,
    there is still no guarantee that a + 1 is properly aligned
    for a struct int_pair_t *.

    Simple question: Is there anything precluding an
    implementation giving struct int_pair_t a stricter
    alignment than int?

    [This is ignoring the issue of effective type which plays
    a further role in the discussion.]

    --
    Peter
    Peter Nilsson, Dec 18, 2009
    #15
  16. On Thu, 17 Dec 2009 19:45:28 -0800 (PST), Peter Nilsson
    <> wrote:

    >Barry Schwarz <> wrote:
    >> Alok Singhal
    >> > Please bear with me while I try to explain myself. Isn't
    >> > there a difference between:
    >> >
    >> > int array[5] = {2};
    >> > int (*ptr)[5] = &array;
    >> >
    >> > and:
    >> >
    >> > int array[20] = {2};
    >> > int (*ptr)[5] = (int (*)[5])(array + 6);

    >>
    >> ...the question revolves around whether a+6 is properly aligned.
    >>
    >> Consider the definition
    >> int x[sizeof(int)][5];

    >
    >I have no idea why you think sizeof(int) should be used here!


    I thought it would insure exhaustion but, as you point out below, it
    works only for currently common implementations and fails in the
    perverse case.

    >
    >> We know that each element x[j] occupies exactly sizeof(int)
    >> bytes. Further more, each element x[j+1] starts exactly
    >> sizeof(int) bytes beyond the start of the previous element
    >> x[j] (except for the obvious boundary condition when j==4).
    >>
    >> We also know that each x is an array of 5 int and that
    >> x[i+1] starts exactly 5*sizeof(int) bytes beyond the start
    >> of x (again except for the boundary condition when i==
    >> sizeof(int)-1).
    >>
    >> Because sizeof(int) is not a factor of 5,

    >
    >Not commonly, but on the virtual machine it may be.
    >
    >> I assert the x as a group completely exhaust all possible
    >> alignments for int[5] and that they also completely exhaust
    >> all possible alignments for int. ...

    >
    >I've had a previous discussion considering something like...
    >
    > int a[7];
    > int (*p)[2] = (int (*)[2]) (a + 1);
    >
    >The problem is whether int(*)[2] can have a stricter
    >alignement than int *. I think it can! I can't see anything
    >in the standard that says a pointer to an element of an array
    >of N elements will always be properly aligned for a pointer
    >to an array of M elements if M < N.


    Yes. If the dimension of the array pointed to is a factor of
    sizeof(int), then my argument fails. For example, if sizeof(int) is 4
    and the alignment for int[2] is 8, then obviously a+1 or a+2 must be
    misaligned for p.

    Applying this to the specific example under consideration where the
    dimension is 5, this can happen only if the alignment for an int[5] is
    a multiple of 5*sizeof(int), such as 20 to match the example. In such
    a case, array+6 may or may not be properly aligned but if it is then
    array+7 is definitely not.

    So to the OP I apologize for the error in my response. It is probably
    properly aligned on all current systems you are likely to run on but
    it may very well invoke undefined behavior on the DS9K or some new
    system where the alignment of int[5] is more restrictive than that of
    int.

    >
    >Why should it? Look at an example using structs...
    >
    > struct int_pair_t { int a; int b; };
    > int a[7];
    > struct int_pair_t *p = (struct int_pair_t *) (a + 1);
    >
    >Even if one shows that there is no padding in the struct,
    >there is still no guarantee that a + 1 is properly aligned
    >for a struct int_pair_t *.
    >
    >Simple question: Is there anything precluding an
    >implementation giving struct int_pair_t a stricter
    >alignment than int?
    >
    >[This is ignoring the issue of effective type which plays
    >a further role in the discussion.]


    --
    Remove del for email
    Barry Schwarz, Dec 19, 2009
    #16
  17. Alok  Singhal

    Alok Singhal Guest

    On Dec 17, 7:02 pm, Barry Schwarz <> wrote:
    >
    > So the question revolves around whether a+6 is properly aligned.


    Yes, I think I wasn't clear enough in my posts so far. This indeed
    was my question to begin with.

    > Consider the definition
    >    int x[sizeof(int)][5];
    >
    > We know that each element x[j] occupies exactly sizeof(int) bytes.
    > Further more, each element x[j+1] starts exactly sizeof(int) bytes
    > beyond the start of the previous element x[j] (except for the
    > obvious boundary condition when j==4).
    >
    > We also know that each x is an array of 5 int and that x[i+1]
    > starts exactly 5*sizeof(int) bytes beyond the start of x (again
    > except for the boundary condition when i==sizeof(int)-1).
    >
    > Because sizeof(int) is not a factor of 5, I assert the x as a group
    > completely exhaust all possible alignments for int[5] and that they
    > also completely exhaust all possible alignments for int.  (I don't
    > remember what the branch of mathematics is called that is used to
    > prove these assertions but if you choose both common (2, 4, and 8) and
    > off-the-wall (3, 15 23) values for sizeof(int) and work out the
    > addresses you should be convinced.)  Consequently, the value a+6 will
    > exactly match the alignment of at least one of the x and is
    > therefore properly aligned.


    OK. I see. I can agree with your arguments. But sizeof(int) can be a
    factor of 5 theoretically, and the number 5 in my original post is
    something I picked out of convenience. In general, it could be any
    number (2, 8, 4, whatever). Similarly, the same goes for the numbers
    and 6, and 20 in my original post. So, given

    int a[N] = {0};
    int (*p)[m] = (int (*)[m])(a+k);

    with N, m, k as integers (and k+m < N of course), I can't be sure if a
    +k is properly aligned for int (*)[m]?

    Thanks a lot for your responses!

    -Alok
    Alok Singhal, Dec 19, 2009
    #17
  18. Alok  Singhal

    Alok Singhal Guest

    On Dec 19, 12:58 am, Barry Schwarz <> wrote:
    > On Thu, 17 Dec 2009 19:45:28 -0800 (PST), Peter Nilsson
    >
    > So to the OP I apologize for the error in my response.  It is probably
    > properly aligned on all current systems you are likely to run on but
    > it may very well invoke undefined behavior on the DS9K or some new
    > system where the alignment of int[5] is more restrictive than that of
    > int.


    No need for the apology - I learned quite a lot from your and Peter's
    answers, and I should have been more specific to begin with. After
    all these years of lurking here in clc, I thought I was ready to post
    an interesting question (interesting to me anyway). :)

    -Alok
    Alok Singhal, Dec 19, 2009
    #18
  19. Alok  Singhal

    Seebs Guest

    On 2009-12-18, Peter Nilsson <> wrote:
    > The problem is whether int(*)[2] can have a stricter
    > alignement than int *. I think it can! I can't see anything
    > in the standard that says a pointer to an element of an array
    > of N elements will always be properly aligned for a pointer
    > to an array of M elements if M < N.


    I am pretty sure arrays don't actually have alignment requirements,
    only the objects in them.

    > Why should it? Look at an example using structs...
    >
    > struct int_pair_t { int a; int b; };
    > int a[7];
    > struct int_pair_t *p = (struct int_pair_t *) (a + 1);
    >
    > Even if one shows that there is no padding in the struct,
    > there is still no guarantee that a + 1 is properly aligned
    > for a struct int_pair_t *.


    For a struct, this might be true. For an array, it's not.

    > Simple question: Is there anything precluding an
    > implementation giving struct int_pair_t a stricter
    > alignment than int?


    I'm not sure. I think in practice you probably can't, because you can
    set up an elaborate construct involving unions which allows you to prove
    that you have to be able to treat a pointer to a large enough hunk of
    space which is aligned properly for an int as a pointer to the first member
    of the structure.

    But structs are not the same thing as arrays. I am pretty sure that
    array-of-foo has to have the same alignment requirements as foo, because
    any foo can be treated as an array of 1 foo, and you can treat any pointer
    to foo as an array of foo. Basically, the wording guaranteeing that
    the offset in bytes of foo[1] is precisely sizeof(foo[0]) covers it.

    So I'm pretty sure that arrays can't have alignment requirements more
    restrictive than the alignment requirements of the things they're arrays
    of.

    -s
    --
    Copyright 2009, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    Seebs, Dec 19, 2009
    #19
  20. Seebs <> writes:
    > On 2009-12-18, Peter Nilsson <> wrote:
    >> The problem is whether int(*)[2] can have a stricter
    >> alignement than int *. I think it can! I can't see anything
    >> in the standard that says a pointer to an element of an array
    >> of N elements will always be properly aligned for a pointer
    >> to an array of M elements if M < N.

    >
    > I am pretty sure arrays don't actually have alignment requirements,
    > only the objects in them.
    >
    >> Why should it? Look at an example using structs...
    >>
    >> struct int_pair_t { int a; int b; };
    >> int a[7];
    >> struct int_pair_t *p = (struct int_pair_t *) (a + 1);
    >>
    >> Even if one shows that there is no padding in the struct,
    >> there is still no guarantee that a + 1 is properly aligned
    >> for a struct int_pair_t *.

    >
    > For a struct, this might be true. For an array, it's not.


    I'd like to think that's true, but I'm not entirely convinced unless
    it can be proven from the standard.

    >> Simple question: Is there anything precluding an
    >> implementation giving struct int_pair_t a stricter
    >> alignment than int?

    >
    > I'm not sure. I think in practice you probably can't, because you can
    > set up an elaborate construct involving unions which allows you to prove
    > that you have to be able to treat a pointer to a large enough hunk of
    > space which is aligned properly for an int as a pointer to the first member
    > of the structure.
    >
    > But structs are not the same thing as arrays. I am pretty sure that
    > array-of-foo has to have the same alignment requirements as foo, because
    > any foo can be treated as an array of 1 foo, and you can treat any pointer
    > to foo as an array of foo. Basically, the wording guaranteeing that
    > the offset in bytes of foo[1] is precisely sizeof(foo[0]) covers it.


    Yes, but it doesn't follow from that that an array type can't have
    a stricter alignment requirement than its element type.

    > So I'm pretty sure that arrays can't have alignment requirements more
    > restrictive than the alignment requirements of the things they're arrays
    > of.


    Consider a hypothetical implementation in which int is 4 bytes (32
    bits), and the CPU has instructions that can access 4-byte and 8-byte
    objects in memory, but only if they're 4-byte or 8-byte aligned.
    The implementation imposes a 4-byte alignment requirement on int
    objects. It also imposes an 8-byte alignment on int[N] objects,
    where N is even. (The question is whether the latter requirement
    is allowed.)

    I declare an arr of int:

    int arr2[4];

    Each element is 4-byte aligned. The object as a whole is 8-byte
    aligned.

    For most operations, everything works just as you'd expect. The
    question is whether this:

    typedef int pair[2];
    pair *p = (pair*)&arr2[1];

    is valid, or whether operations on p can invoke undefined behavior
    because of the alignment mismatch.

    If an implementation causes the initialization of p to trap, for
    example, what clause of the standard does the implementation violate?

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Dec 19, 2009
    #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. sangeetha

    Array of pointer Vs Pointer to Array

    sangeetha, Oct 8, 2004, in forum: C Programming
    Replies:
    9
    Views:
    346
    Tim Rentsch
    Oct 9, 2004
  2. erfan

    Array of pointer and pointer of array

    erfan, Jan 28, 2008, in forum: C Programming
    Replies:
    6
    Views:
    673
    Martin Ambuhl
    Jan 28, 2008
  3. RSL
    Replies:
    14
    Views:
    3,246
  4. Hansen
    Replies:
    3
    Views:
    1,098
    rep_movsd
    Apr 24, 2010
  5. , India

    pointer to an array vs pointer to pointer

    , India, Sep 20, 2011, in forum: C Programming
    Replies:
    5
    Views:
    449
    James Kuyper
    Sep 23, 2011
Loading...

Share This Page