Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > const array of const pointers as a parameter

Reply
Thread Tools

const array of const pointers as a parameter

 
 
Spoon
Guest
Posts: n/a
 
      10-18-2006
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?
 
Reply With Quote
 
 
 
 
Darko
Guest
Posts: n/a
 
      10-18-2006
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?


 
Reply With Quote
 
 
 
 
arne
Guest
Posts: n/a
 
      10-18-2006
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.

 
Reply With Quote
 
Andrey Tarasevich
Guest
Posts: n/a
 
      10-18-2006
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-lit...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
 
Reply With Quote
 
A. Bolmarcich
Guest
Posts: n/a
 
      10-18-2006
On 2006-10-18, Spoon <(E-Mail Removed)> 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.
 
Reply With Quote
 
John Bode
Guest
Posts: n/a
 
      10-18-2006

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?


 
Reply With Quote
 
lawrence.jones@ugs.com
Guest
Posts: n/a
 
      10-18-2006
Andrey Tarasevich <(E-Mail Removed)> 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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Resolving ambiguity between pointers to const and non-const members. Vladimir Menshakov C++ 1 05-15-2011 08:15 AM
pointers, pointers, pointers... cerr C Programming 12 04-07-2011 11:17 PM
std::list with const and non-const pointers - why aren't they typecompatible? arijit79@gmail.com C++ 4 03-02-2009 07:57 AM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM
problems with const pointers to const objects Tim Partridge C++ 2 02-05-2004 08:53 PM



Advertisments