const array of const pointers as a parameter

Discussion in 'C Programming' started by Spoon, Oct 18, 2006.

  1. Spoon

    Spoon Guest

    Hello,

    I don't understand why gcc barks at me in this situation:

    $ cat foo.c
    extern void func(const int * const list[], int nent);

    int main(void)
    {
    int *p[5];
    func(p, 5);
    return 0;
    }

    $ gcc -Wall -std=c89 -c foo.c
    foo.c: In function `main':
    foo.c:6: warning: passing arg 1 of `func' from incompatible pointer type

    AFAIU, func promises not to change the values pointed to by the pointers
    in the array (i.e. *list[2] = 666 is illegal) AND not to change the
    pointers themselves (i.e. list[2] = NULL is also illegal).

    I don't understand what the compiler dislikes about p.

    Could someone enlighten me?
    Spoon, Oct 18, 2006
    #1
    1. Advertising

  2. Spoon

    Darko Guest

    Hm. I myself too had trouble with consts pretty much the same way you
    do now. As far as I can recall, multiple consts in the same expression
    are not allowed by ANSI. However, lots of things seem not to be allowed
    by ANSI and yet are quite normal in practice.

    Anyway, my humble opinion is that you should try adding another const
    at the and of your "list" expression, like in: const int * const * list
    const. That way you declare list to be constant, too, which is true
    because what you've got down there is a static array, which is actually
    a constant pointer to another pointer.

    I would try it myself but I don't have Linux here at work.

    Bye,

    Darko

    Spoon wrote:
    > Hello,
    >
    > I don't understand why gcc barks at me in this situation:
    >
    > $ cat foo.c
    > extern void func(const int * const list[], int nent);
    >
    > int main(void)
    > {
    > int *p[5];
    > func(p, 5);
    > return 0;
    > }
    >
    > $ gcc -Wall -std=c89 -c foo.c
    > foo.c: In function `main':
    > foo.c:6: warning: passing arg 1 of `func' from incompatible pointer type
    >
    > AFAIU, func promises not to change the values pointed to by the pointers
    > in the array (i.e. *list[2] = 666 is illegal) AND not to change the
    > pointers themselves (i.e. list[2] = NULL is also illegal).
    >
    > I don't understand what the compiler dislikes about p.
    >
    > Could someone enlighten me?
    Darko, Oct 18, 2006
    #2
    1. Advertising

  3. Spoon

    arne Guest

    Spoon schrieb:

    > Hello,
    >
    > I don't understand why gcc barks at me in this situation:
    >
    > $ cat foo.c
    > extern void func(const int * const list[], int nent);
    >
    > int main(void)
    > {
    > int *p[5];
    > func(p, 5);
    > return 0;
    > }
    >
    > $ gcc -Wall -std=c89 -c foo.c
    > foo.c: In function `main':
    > foo.c:6: warning: passing arg 1 of `func' from incompatible pointer type
    >
    > AFAIU, func promises not to change the values pointed to by the pointers
    > in the array (i.e. *list[2] = 666 is illegal) AND not to change the
    > pointers themselves (i.e. list[2] = NULL is also illegal).
    >
    > I don't understand what the compiler dislikes about p.
    >
    > Could someone enlighten me?


    What about changing

    int *p[5];

    to

    const int *p[5]; ?


    The function expects an array of const pointers to const ints, but you
    pass an array of pointers to ints.
    arne, Oct 18, 2006
    #3
  4. Spoon wrote:
    > Hello,
    >
    > I don't understand why gcc barks at me in this situation:
    >
    > $ cat foo.c
    > extern void func(const int * const list[], int nent);
    >
    > int main(void)
    > {
    > int *p[5];
    > func(p, 5);
    > return 0;
    > }
    >
    > $ gcc -Wall -std=c89 -c foo.c
    > foo.c: In function `main':
    > foo.c:6: warning: passing arg 1 of `func' from incompatible pointer type
    >
    > AFAIU, func promises not to change the values pointed to by the pointers
    > in the array (i.e. *list[2] = 666 is illegal) AND not to change the
    > pointers themselves (i.e. list[2] = NULL is also illegal).
    >
    > I don't understand what the compiler dislikes about p.
    > ...


    The function parameter declaration is equivalent to 'const int* const* list'.
    The type of actual argument (array 'p') decays to 'int**'. In other words, you
    are trying to initialize an object of type 'const int* const*' with a value of
    type 'int**'. This is not allowed by const-correctness rules of C language. The
    culprit is the first 'const' from the left. C language allows you to "add" a
    'const' at the first level of indirection, but not at any deeper level of
    indirection. I.e. it is OK to convert 'int**' to 'int* const*', but it is not OK
    to convert it to either 'const int**' or 'const int* const*'.

    The rationale behind this is described in the following C++ (sic) FAQ entry

    http://www.parashift.com/c -faq-lite/const-correctness.html#faq-18.17

    This is a C++ FAQ entry, but it does explain the issue very well. (There's also
    a similar example in C99 standard.) However, C++ language adopted a more
    elaborate behavior in this case and, as a result, C++ actually _allows_ the
    'int**' to 'const int* const*' conversion (still disallowing the conversion to
    'const int**'). C language decided to stay with a more primitive/simplified
    specification, meaning that 'int**' to 'const int* const*' conversion is
    outlawed in C, even though it's harmless from the const-correctness point of view.

    --
    Best regards,
    Andrey Tarasevich
    Andrey Tarasevich, Oct 18, 2006
    #4
  5. On 2006-10-18, Spoon <> wrote:
    > Hello,
    >
    > I don't understand why gcc barks at me in this situation:
    >
    > $ cat foo.c
    > extern void func(const int * const list[], int nent);
    >
    > int main(void)
    > {
    > int *p[5];
    > func(p, 5);
    > return 0;
    > }
    >
    > $ gcc -Wall -std=c89 -c foo.c
    > foo.c: In function `main':
    > foo.c:6: warning: passing arg 1 of `func' from incompatible pointer type
    >
    > AFAIU, func promises not to change the values pointed to by the pointers
    > in the array (i.e. *list[2] = 666 is illegal) AND not to change the
    > pointers themselves (i.e. list[2] = NULL is also illegal).
    >
    > I don't understand what the compiler dislikes about p.
    >
    > Could someone enlighten me?


    The assignment constraint in the C89 specification being used in this
    case is

    both operands are pointers to qualified or unqualified types verisons
    of compatible types, and the type pointed to by the left has all the
    qualifiers as the type pointed to by the right

    Also, according th the C89 specification

    For two qualified types to be compatible, both shall have the identical
    qualified versions of a compatible type

    The argument type is pointerTo-pointerTo-int and the parameter type is
    pointerTo-pointerTo-const-int. According to the C89 specification
    a pointerTo-int is not compatible with pointerTo-const-int because they
    are not identically qualified.

    The assignment constraint allows the parameter to have additional
    "top-level" pointer qualifiers that the argument does not have. This
    allows a (* int) argument to be assigned to a (const * int) parameter.
    However, that constraint does not apply to "inner-level" pointers which
    need to be identically qualified.
    A. Bolmarcich, Oct 18, 2006
    #5
  6. Spoon

    John Bode Guest

    Spoon wrote:
    > Hello,
    >
    > I don't understand why gcc barks at me in this situation:
    >
    > $ cat foo.c
    > extern void func(const int * const list[], int nent);
    >
    > int main(void)
    > {
    > int *p[5];


    This is not an array of constant pointers. That's why you're getting
    barked at.

    If you declare it as

    int const *p[5];

    the code should compile (it does for me, anyway). Whether that's what
    you really *want* to do is an open question (I suspect it isn't).

    > func(p, 5);
    > return 0;
    > }
    >
    > $ gcc -Wall -std=c89 -c foo.c
    > foo.c: In function `main':
    > foo.c:6: warning: passing arg 1 of `func' from incompatible pointer type
    >
    > AFAIU, func promises not to change the values pointed to by the pointers
    > in the array (i.e. *list[2] = 666 is illegal) AND not to change the
    > pointers themselves (i.e. list[2] = NULL is also illegal).
    >
    > I don't understand what the compiler dislikes about p.
    >
    > Could someone enlighten me?
    John Bode, Oct 18, 2006
    #6
  7. Spoon

    Guest

    Andrey Tarasevich <> wrote:
    >
    > This is a C++ FAQ entry, but it does explain the issue very well. (There's also
    > a similar example in C99 standard.) However, C++ language adopted a more
    > elaborate behavior in this case and, as a result, C++ actually _allows_ the
    > 'int**' to 'const int* const*' conversion (still disallowing the conversion to
    > 'const int**'). C language decided to stay with a more primitive/simplified
    > specification, meaning that 'int**' to 'const int* const*' conversion is
    > outlawed in C, even though it's harmless from the const-correctness point of view.


    In particular, the original C rules were developed before the C++ rules
    had been worked out. Once they were, the way C++ describes the common
    language is sufficiently different from the way C describes it that the
    rules could not just be lifted verbatim but would have to be rewritten
    (in particular, I seem to recall some unrelated handwaving in the C++
    standard that happens to make arrays work out right that does not exist
    in the C standard). Also, C added the restrict type qualifier, which
    complicates the rules since it does not work the same way as const and
    volatile do. So far as I know, no one has worked out the rules with
    restrict included.

    -Larry Jones

    Hey Doc, for 10 bucks I'll make sure you see those kids in the
    waiting room again real soon! -- Calvin
    , Oct 18, 2006
    #7
    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. Tim Partridge
    Replies:
    2
    Views:
    320
    Jonathan Turkanis
    Feb 5, 2004
  2. Javier
    Replies:
    2
    Views:
    544
    James Kanze
    Sep 4, 2007
  3. Replies:
    4
    Views:
    2,615
  4. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    654
  5. Vladimir Menshakov
    Replies:
    1
    Views:
    353
Loading...

Share This Page