2D const array nested functions warning question

Discussion in 'C Programming' started by Andres Meyer, Feb 27, 2008.

  1. Andres Meyer

    Andres Meyer Guest

    Hello,

    I am trying to compile the very simple program below and am getting this
    error:

    $ gcc -Wall -ansi -o test test.c
    test.c: In function âmainâ:
    test.c:17: warning: passing argument 1 of âf2â from incompatible pointer
    type

    $ gcc --version
    gcc (GCC) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)


    Could someone tell me what trivial thing I am doing wrong? I am just
    trying to make the int values of the array not modifiable in both
    functions. I do not get this warning without the const modifiers.

    Cheers,
    Andres


    test.c:

    #include <stdio.h>

    void f1(const int i[][2])
    {
    printf("%d\n", i[0][0]);
    }

    void f2(const int j[][2])
    {
    f1(j);
    }

    int main()
    {
    int m[2][2];
    m[0][0] = 5;
    f2(m);
    return 0;
    }
     
    Andres Meyer, Feb 27, 2008
    #1
    1. Advertising

  2. Andres Meyer

    Micah Cowan Guest

    Andres Meyer wrote:
    > Could someone tell me what trivial thing I am doing wrong? I am just
    > trying to make the int values of the array not modifiable in both
    > functions. I do not get this warning without the const modifiers.



    > void f1(const int i[][2])


    As a parameter, i is equivalent to:
    const int (*i)[2]
    a pointer to an array of 2 const int.

    > int m[2][2];

    ....
    > f2(m);

    This passes an int (*i)[2], or pointer to an array of 2 int.

    The problem you're having stems from the fact that pointers to FOO
    aren't compatible with pointers to BAR, where BAR is declared the same
    as FOO, except there are extra const specifiers buried in there.

    C makes a _special_ exception for assigning pointers to FOO to pointers
    of const FOO. Unfortunately, what you have here is a pointer to an
    _array_ of const FOO. If the "const" isn't right after "pointer", it's
    not allowed. What you'd want is a "pointer to a const array of int"

    What sucks about this, of course, is that there really would be no
    semantic difference between "pointer to an array of const int", and
    "pointer to a const array of int"; but there isn't a way to declare the
    latter, while the former still technically fails to meet the special
    assignment exception. One might think you could do:

    typedef int ary[2]; /* ary is array 2 of int */
    const ary *foo; /* foo is const array 2 of int */

    But you can't: C still defines that (under the definition for type
    qualifiers) as "an array 2 of const int". :(

    I'm actually not sure how you could manage this without a cast (which
    will give undefined behavior if you use the result, though it's
    extremely likely to work "as expected" on any actual implementation).
    Your best bet may be to use it without the const qualifiers.

    I'm hoping someone will jump in now with a clever workaround.

    --
    Micah J. Cowan
    Programmer, musician, typesetting enthusiast, gamer...
    http://micah.cowan.name/
     
    Micah Cowan, Feb 27, 2008
    #2
    1. Advertising

  3. Andres Meyer wrote:
    > ...
    > Could someone tell me what trivial thing I am doing wrong?
    > ...


    It is just one of the quirks of the language. Normally one'd expect that
    a value of type 'T*' can be implicitly converted to type 'const T*'.
    This is true most of the time, but unfortunately when 'T' is an array
    type the conversion is not allowed

    typedef int T[2];
    T* p = 0;
    const T* c = p; // <- ERROR

    That's just an unpleasant side-effect of the way the const-correctness
    rules are formulated in C. And this is exactly what happens in your
    code, if you analyze it carefully.

    C++ went with a more elaborate specification, which makes more sense and
    doesn't suffer from this issue, but C continues to stick with that old
    strange one for some reason.

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Feb 27, 2008
    #3
  4. On Wed, 27 Feb 2008 19:20:52 GMT, Micah Cowan <>
    wrote:

    > Andres Meyer wrote:


    > > void f1(const int i[][2])

    >
    > As a parameter, i is equivalent to:
    > const int (*i)[2]
    > a pointer to an array of 2 const int.
    >
    > > int m[2][2];

    > ...
    > > f2(m);

    > This passes an int (*i)[2], or pointer to an array of 2 int.
    >
    > The problem you're having stems from the fact that pointers to FOO
    > aren't compatible with pointers to BAR, where BAR is declared the same
    > as FOO, except there are extra const specifiers buried in there.
    >
    > C makes a _special_ exception for assigning pointers to FOO to pointers
    > of const FOO. Unfortunately, what you have here is a pointer to an
    > _array_ of const FOO. If the "const" isn't right after "pointer", it's
    > not allowed. What you'd want is a "pointer to a const array of int"
    >

    Agree so far.

    <snip>
    > I'm actually not sure how you could manage this without a cast (which
    > will give undefined behavior if you use the result, though it's
    > extremely likely to work "as expected" on any actual implementation).


    Yes you need the cast, but no it doesn't produce UB.

    The qualified type has the same alignment requirement (6.2.5p25) and
    the cast of a valid pointer value (as here) produces a valid and equal
    one (6.3.2.3p2,7) and derefencing it gives a valid (though qualified)
    lvalue which can correctly be used to read the object (6.5p7).

    Attempting to deconstify and write an object _defined_ const is UB,
    but that's not the situation here.

    > Your best bet may be to use it without the const qualifiers.
    >

    That is indeed easier.

    - formerly david.thompson1 || achar(64) || worldnet.att.net
     
    David Thompson, Mar 10, 2008
    #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:
    14
    Views:
    696
    Kai-Uwe Bux
    Sep 18, 2006
  2. Replies:
    11
    Views:
    1,108
  3. Javier
    Replies:
    2
    Views:
    565
    James Kanze
    Sep 4, 2007
  4. 0m
    Replies:
    26
    Views:
    1,122
    Tim Rentsch
    Nov 10, 2008
  5. fungus
    Replies:
    13
    Views:
    892
    fungus
    Oct 31, 2008
Loading...

Share This Page