const and array of array (of array ...)

Discussion in 'C Programming' started by Mara Guida, Sep 2, 2009.

  1. Mara Guida

    Mara Guida Guest

    Imagine I have an array of arrays of ints and want to sum all the
    ints.

    #include <stdio.h>

    int sumints(int arr[3][3])
    {
    int c, r, s=0;
    for (r=0; r<3; r++)
    {
    for (c=0; c<3; c++) {
    s += arr[r][c];
    }
    }
    return s;
    }

    int main(void)
    {
    int my_array[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
    printf("sum of ints is %d\n", sumints(my_array));
    return 0;
    }

    I tried to define the sumints() function with constant ints, but the
    types are not compatible

    int sumints(const int arr[3][3])

    I understand arrays 'decay' into a pointer to their first element when
    passed to functions.
    I understand the elements of the array `my_array` are not int: they
    are arrays[3] of int.

    I tried several variations on the theme (mostly using typedefs) and
    reached the conclusion that
    a pointer to an array[3] of int is compatible with
    1) a constant pointer to an array[3] of int
    2) a pointer to a constant array[3] of int
    3) a constant pointer to a constant array[3] of int





    Why aren't

    int (*a)[3] /* a is a pointer to an array[3] of int */
    and
    const int (*a)[3] /* a is a pointer to an array[3] of
    constant int */

    compatible types?


    It shouldn't be too hard for the compiler to figure it out, right?
    Mara Guida, Sep 2, 2009
    #1
    1. Advertising

  2. Mara Guida

    David RF Guest

    On 2 sep, 22:37, Mara Guida <> wrote:
    > Imagine I have an array of arrays of ints and want to sum all the
    > ints.
    >
    >         #include <stdio.h>
    >
    >         int sumints(int arr[3][3])
    >         {
    >             int c, r, s=0;
    >             for (r=0; r<3; r++)
    >             {
    >                 for (c=0; c<3; c++) {
    >                     s += arr[r][c];
    >                 }
    >             }
    >             return s;
    >         }
    >
    >         int main(void)
    >         {
    >             int my_array[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
    >             printf("sum of ints is %d\n", sumints(my_array));
    >             return 0;
    >         }
    >
    > I tried to define the sumints() function with constant ints, but the
    > types are not compatible
    >
    >         int sumints(const int arr[3][3])
    >
    > I understand arrays 'decay' into a pointer to their first element when
    > passed to functions.
    > I understand the elements of the array `my_array` are not int: they
    > are arrays[3] of int.
    >
    > I tried several variations on the theme (mostly using typedefs) and
    > reached the conclusion that
    >         a pointer to an array[3] of int is compatible with
    >                 1) a constant pointer to an array[3] of int
    >                 2) a pointer to a constant array[3] of int
    >                 3) a constant pointer to a constant array[3] of int
    >
    > Why aren't
    >
    >         int (*a)[3]    /* a is a pointer to an array[3] of int */
    > and
    >         const int (*a)[3]    /* a is a pointer to an array[3] of
    > constant int */
    >
    > compatible types?
    >
    > It shouldn't be too hard for the compiler to figure it out, right?


    Take a look to this thread:
    http://groups.google.com/group/comp.lang.c/browse_thread/thread/677fe66ded99b7a2
    David RF, Sep 2, 2009
    #2
    1. Advertising

  3. Mara Guida <> writes:

    > Imagine I have an array of arrays of ints and want to sum all the
    > ints.
    >
    > #include <stdio.h>
    >
    > int sumints(int arr[3][3])
    > {
    > int c, r, s=0;
    > for (r=0; r<3; r++)
    > {
    > for (c=0; c<3; c++) {
    > s += arr[r][c];
    > }
    > }
    > return s;
    > }
    >
    > int main(void)
    > {
    > int my_array[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
    > printf("sum of ints is %d\n", sumints(my_array));
    > return 0;
    > }
    >
    > I tried to define the sumints() function with constant ints, but the
    > types are not compatible
    >
    > int sumints(const int arr[3][3])
    >
    > I understand arrays 'decay' into a pointer to their first element when
    > passed to functions.
    > I understand the elements of the array `my_array` are not int: they
    > are arrays[3] of int.


    Yup...

    > I tried several variations on the theme (mostly using typedefs) and
    > reached the conclusion that
    > a pointer to an array[3] of int is compatible with
    > 1) a constant pointer to an array[3] of int
    > 2) a pointer to a constant array[3] of int
    > 3) a constant pointer to a constant array[3] of int


    .... but here you have been led astray, possibly by the compiler's
    original error message and subsequent lack of a message.

    Type compatibility is very strict and all of your examples are
    incompatible with each other. When gcc complains that you are
    "passing argument 1 of 'sumints' from incompatible pointer type" it is
    true but not the whole story. For example, you can pass an argument
    of type int * to function that takes a const int * but these two types
    are not compatible.

    Parameter passing is defined as assignment in C and pointer assignment
    requires that

    "both operands are pointers to qualified or unqualified versions of
    compatible types, and the type pointed to by the left has all the
    qualifiers of the type pointed to by the right" [6.5.16.1 p1]

    So, you can pass an int * to a const int * parameter because both are
    pointer to qualified or unqualified versions of compatible types (int
    in this case) and the type pointed to left (const int) has all the
    qualifiers of the type pointed to by the right (int).

    > Why aren't
    >
    > int (*a)[3] /* a is a pointer to an array[3] of int */
    > and
    > const int (*a)[3] /* a is a pointer to an array[3] of
    > constant int */
    >
    > compatible types?


    In this case, both are not pointers to qualified or unqualified
    versions of compatible types. The two types pointed to are int[3] and
    const int[3] and neither of these is qualified, so the only issue
    whether are they compatible and they are not. (Arrays are compatible
    only if the element types are compatible and int and const int are
    not.)

    The point of all this verbiage is that when assigning and passing
    parameters a qualifier can be added only to[1] the immediately
    pointed-to type and not to the element type of a pointed-to array or,
    indeed, of another pointer.

    The compiler resorts to saying "not compatible" partly because that
    is indeed true but mainly, I suspect, because there is no word for
    this slightly weaker "assignable" type test.

    > It shouldn't be too hard for the compiler to figure it out, right?


    With the correction that actual compatibility is not the issue, you
    have a valid point and it has come up here often -- most usually when
    passing a T ** to a function with a const T ** parameter. There is
    not good technical answer. C went with a simple rule that makes some
    obvious things need a cast (C++, for example, has a more complex rule
    that permits such things).

    [1] Parameters themselves can also be declared const but that is
    ignored for all these determinations.

    --
    Ben.
    Ben Bacarisse, Sep 2, 2009
    #3
  4. Mara Guida

    David RF Guest

    On 2 sep, 22:37, Mara Guida <> wrote:
    > Imagine I have an array of arrays of ints and want to sum all the
    > ints.
    >
    >         #include <stdio.h>
    >
    >         int sumints(int arr[3][3])
    >         {
    >             int c, r, s=0;
    >             for (r=0; r<3; r++)
    >             {
    >                 for (c=0; c<3; c++) {
    >                     s += arr[r][c];
    >                 }
    >             }
    >             return s;
    >         }
    >
    >         int main(void)
    >         {
    >             int my_array[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
    >             printf("sum of ints is %d\n", sumints(my_array));
    >             return 0;
    >         }
    >
    > I tried to define the sumints() function with constant ints, but the
    > types are not compatible
    >
    >         int sumints(const int arr[3][3])
    >
    > I understand arrays 'decay' into a pointer to their first element when
    > passed to functions.
    > I understand the elements of the array `my_array` are not int: they
    > are arrays[3] of int.
    >
    > I tried several variations on the theme (mostly using typedefs) and
    > reached the conclusion that
    >         a pointer to an array[3] of int is compatible with
    >                 1) a constant pointer to an array[3] of int
    >                 2) a pointer to a constant array[3] of int
    >                 3) a constant pointer to a constant array[3] of int
    >
    > Why aren't
    >
    >         int (*a)[3]    /* a is a pointer to an array[3] of int */
    > and
    >         const int (*a)[3]    /* a is a pointer to an array[3] of
    > constant int */
    >
    > compatible types?
    >
    > It shouldn't be too hard for the compiler to figure it out, right?


    Try this:

    #include <stdio.h>

    int sumints(const int arr[3][3]);
    int sumints(const int arr[3][3])
    {
    int c, r, s = 0;

    for (r = 0; r < 3; r++) {
    for (c = 0; c < 3; c++) {
    s += arr[r][c];
    }
    }
    return s;
    }

    int main(void)
    {
    int arr[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};

    printf("sum of ints is %d\n", sumints((const int (*)[])arr));
    return 0;

    }
    David RF, Sep 3, 2009
    #4
    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. Replies:
    11
    Views:
    1,101
  2. Javier
    Replies:
    2
    Views:
    561
    James Kanze
    Sep 4, 2007
  3. 0m
    Replies:
    26
    Views:
    1,115
    Tim Rentsch
    Nov 10, 2008
  4. fungus
    Replies:
    13
    Views:
    887
    fungus
    Oct 31, 2008
  5. Replies:
    2
    Views:
    541
    Andrew Koenig
    Feb 9, 2009
Loading...

Share This Page