Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #99623 > unrolled thread

Incompatible pointer types with GCC

Started byAugust Karlstrom <fusionfile@gmail.com>
First post2016-12-16 11:41 +0100
Last post2016-12-29 13:33 -0800
Articles 9 — 6 participants

Back to article view | Back to comp.lang.c


Contents

  Incompatible pointer types with GCC August Karlstrom <fusionfile@gmail.com> - 2016-12-16 11:41 +0100
    Re: Incompatible pointer types with GCC BartC <bc@freeuk.com> - 2016-12-16 11:06 +0000
    Re: Incompatible pointer types with GCC Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-12-16 17:07 +0000
      Re: Incompatible pointer types with GCC August Karlstrom <fusionfile@gmail.com> - 2016-12-16 23:02 +0100
        Re: Incompatible pointer types with GCC Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-12-17 00:48 +0000
        Re: Incompatible pointer types with GCC martin.uecker@med.uni-goettingen.de - 2016-12-18 08:06 -0800
          Re: Incompatible pointer types with GCC Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-12-18 20:11 +0000
            Re: Incompatible pointer types with GCC supercat@casperkitty.com - 2016-12-18 14:43 -0800
              Re: Incompatible pointer types with GCC Tim Rentsch <txr@alumni.caltech.edu> - 2016-12-29 13:33 -0800

#99623 — Incompatible pointer types with GCC

FromAugust Karlstrom <fusionfile@gmail.com>
Date2016-12-16 11:41 +0100
SubjectIncompatible pointer types with GCC
Message-ID<o30g9b$v1l$1@dont-email.me>
My question is whether this is a valid ANSI C (C89) program or not:

	typedef int Row[10];
	
	void P(const Row A[])
	{
	}
	
	
	int main(void)
	{
	    Row A[10];
	
	    P(A);
	    return 0;
	}

It compiles cleanly with Clang 3.5.0 and the options -pedantic -std=c89 
-Wall.

GCC 4.9.2, however, is not happy:

$ gcc -c -o test.o -g -pedantic -std=c89 -Wall test.c
test.c: In function ‘main’:
test.c:12:4: warning: passing argument 1 of ‘P’ from incompatible 
pointer type
   P(A);
     ^
test.c:3:6: note: expected ‘const int (*)[10]’ but argument is of type 
‘int (*)[10]’
  void P(const Row A[])
       ^

Any clues?


Regards,
August

[toc] | [next] | [standalone]


#99627

FromBartC <bc@freeuk.com>
Date2016-12-16 11:06 +0000
Message-ID<o30ho7$4c1$1@dont-email.me>
In reply to#99623
On 16/12/2016 10:41, August Karlstrom wrote:
> My question is whether this is a valid ANSI C (C89) program or not:
>
>     typedef int Row[10];
>
>     void P(const Row A[])
>     {
>     }
>
>
>     int main(void)
>     {
>         Row A[10];
>
>         P(A);
>         return 0;
>     }
>
> It compiles cleanly with Clang 3.5.0 and the options -pedantic -std=c89
> -Wall.
>
> GCC 4.9.2, however, is not happy:
>
> $ gcc -c -o test.o -g -pedantic -std=c89 -Wall test.c
> test.c: In function ‘main’:
> test.c:12:4: warning: passing argument 1 of ‘P’ from incompatible
> pointer type
>   P(A);
>     ^
> test.c:3:6: note: expected ‘const int (*)[10]’ but argument is of type
> ‘int (*)[10]’
>  void P(const Row A[])
>       ^
>
> Any clues?

I get:

c.c:16:9: warning: pointers to arrays with different qualifiers are 
incompatible in ISO C [-Wpedantic]
          P(A);
          ^

I suspect that, because of the typedef 'Row', the 'const' doesn't apply 
to the bit that you think it does. Try dumping 'const' for now and add 
it later when the program works.

Or remove the typedef which I think causes problems with arrays.

-- 
Bartc

[toc] | [prev] | [next] | [standalone]


#99665

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-12-16 17:07 +0000
Message-ID<87eg172468.fsf@bsb.me.uk>
In reply to#99623
August Karlstrom <fusionfile@gmail.com> writes:

> My question is whether this is a valid ANSI C (C89) program or not:
>
> 	typedef int Row[10];
>
> 	void P(const Row A[])

The [] might confuse some people.  This is simply

        void P(const Row *A)
> 	{
> 	}
>
> 	int main(void)
> 	{
> 	    Row A[10];
>
> 	    P(A);
> 	    return 0;
> 	}
>
> It compiles cleanly with Clang 3.5.0 and the options -pedantic
> -std=c89 -Wall.
>
> GCC 4.9.2, however, is not happy:
>
> $ gcc -c -o test.o -g -pedantic -std=c89 -Wall test.c
> test.c: In function ‘main’:
> test.c:12:4: warning: passing argument 1 of ‘P’ from incompatible
> pointer type
>   P(A);
>     ^
> test.c:3:6: note: expected ‘const int (*)[10]’ but argument is of type
> ‘int (*)[10]’
>  void P(const Row A[])
>       ^
>
> Any clues?

I think gcc is right to complain.

Whilst the types are not compatible, that's not really the problem here.
For example, you can pass an int * to a function that takes const int *
and those two types are not compatible.  Argument passing is done "as if
by assignment", and in an assignment the pointed-to type on the left can
have extra qualifiers.  But here, the const qualifies the element type,
not the pointed-to type, which is an array type.  (C has not qualified
array types at all).

The call is safe, of course, but C chose to use a simple rule rather
than trying to identify only those calls (and assignments) that are not
safe.  C++ has a more comprehensive rule.

Cases like this (and passing to a const T ** parameter) are some of the
rare times when you really need a cast.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#99708

FromAugust Karlstrom <fusionfile@gmail.com>
Date2016-12-16 23:02 +0100
Message-ID<o31o7a$f7g$1@dont-email.me>
In reply to#99665
On 2016-12-16 18:07, Ben Bacarisse wrote:
> August Karlstrom <fusionfile@gmail.com> writes:
> The [] might confuse some people.  This is simply
>
>         void P(const Row *A)

I prefer to use brackets when a sequence is expected, it provides more 
semantic information.

>> test.c:3:6: note: expected ‘const int (*)[10]’ but argument is of type
>> ‘int (*)[10]’
>>  void P(const Row A[])
>>       ^
>
> I think gcc is right to complain.
>
> Whilst the types are not compatible, that's not really the problem here.
> For example, you can pass an int * to a function that takes const int *
> and those two types are not compatible.  Argument passing is done "as if
> by assignment", and in an assignment the pointed-to type on the left can
> have extra qualifiers.  But here, the const qualifies the element type,
> not the pointed-to type, which is an array type.  (C has not qualified
> array types at all).

That's counter-intuitive. I thought const applied to Row.

> The call is safe, of course, but C chose to use a simple rule rather
> than trying to identify only those calls (and assignments) that are not
> safe.  C++ has a more comprehensive rule.
>
> Cases like this (and passing to a const T ** parameter) are some of the
> rare times when you really need a cast.

OK, thanks for the clarification.


-- August

[toc] | [prev] | [next] | [standalone]


#99717

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-12-17 00:48 +0000
Message-ID<87lgvfz8hi.fsf@bsb.me.uk>
In reply to#99708
August Karlstrom <fusionfile@gmail.com> writes:

> On 2016-12-16 18:07, Ben Bacarisse wrote:
>> August Karlstrom <fusionfile@gmail.com> writes:
>> The [] might confuse some people.  This is simply
>>
>>         void P(const Row *A)
>
> I prefer to use brackets when a sequence is expected, it provides more
> semantic information.

Yes, that's a reasonable thing to do, but I thought it best to clarify
(for others) that A is a plain old pointer.

>>> test.c:3:6: note: expected ‘const int (*)[10]’ but argument is of type
>>> ‘int (*)[10]’
>>>  void P(const Row A[])
>>>       ^
>>
>> I think gcc is right to complain.
>>
>> Whilst the types are not compatible, that's not really the problem here.
>> For example, you can pass an int * to a function that takes const int *
>> and those two types are not compatible.  Argument passing is done "as if
>> by assignment", and in an assignment the pointed-to type on the left can
>> have extra qualifiers.  But here, the const qualifies the element type,
>> not the pointed-to type, which is an array type.  (C has not qualified
>> array types at all).
>
> That's counter-intuitive. I thought const applied to Row.

Well... in some way it does, it's just that qualifying an array type
means qualifying the element type.

>> The call is safe, of course, but C chose to use a simple rule rather
>> than trying to identify only those calls (and assignments) that are not
>> safe.  C++ has a more comprehensive rule.
>>
>> Cases like this (and passing to a const T ** parameter) are some of the
>> rare times when you really need a cast.
>
> OK, thanks for the clarification.

Hang on for a bit, just in case someone decides I got it all wrong!

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#99810

Frommartin.uecker@med.uni-goettingen.de
Date2016-12-18 08:06 -0800
Message-ID<641f9236-55db-4b01-aab0-4848d055318f@googlegroups.com>
In reply to#99708
On Friday, December 16, 2016 at 11:02:46 PM UTC+1, August Karlstrom wrote:
> On 2016-12-16 18:07, Ben Bacarisse wrote:
> > August Karlstrom <fusionfile@gmail.com> writes:
> > The [] might confuse some people.  This is simply
> >
> >         void P(const Row *A)
> 
> I prefer to use brackets when a sequence is expected, it provides more 
> semantic information.
> 
> >> test.c:3:6: note: expected ‘const int (*)[10]’ but argument is of type
> >> ‘int (*)[10]’
> >>  void P(const Row A[])
> >>       ^
> >
> > I think gcc is right to complain.
> >
> > Whilst the types are not compatible, that's not really the problem here.
> > For example, you can pass an int * to a function that takes const int *
> > and those two types are not compatible.  Argument passing is done "as if
> > by assignment", and in an assignment the pointed-to type on the left can
> > have extra qualifiers.  But here, the const qualifies the element type,
> > not the pointed-to type, which is an array type.  (C has not qualified
> > array types at all).
> 
> That's counter-intuitive. I thought const applied to Row.

Yes, I hope (and it seems) that this gets fixed in the next revision
of the C standard. Arrays should behave like structs with respect
to const but currently they don't. 

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1923.htm


Without '-pedantic' gcc will accept this, so I recommend to use
this non-standard extension instead of adding casts which
break type safety. 

Martin

[toc] | [prev] | [next] | [standalone]


#99836

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-12-18 20:11 +0000
Message-ID<87r3555769.fsf@bsb.me.uk>
In reply to#99810
martin.uecker@med.uni-goettingen.de writes:

> On Friday, December 16, 2016 at 11:02:46 PM UTC+1, August Karlstrom wrote:
>> On 2016-12-16 18:07, Ben Bacarisse wrote:
>> > August Karlstrom <fusionfile@gmail.com> writes:
>> > The [] might confuse some people.  This is simply
>> >
>> >         void P(const Row *A)
>> 
>> I prefer to use brackets when a sequence is expected, it provides more 
>> semantic information.
>> 
>> >> test.c:3:6: note: expected ‘const int (*)[10]’ but argument is of type
>> >> ‘int (*)[10]’
>> >>  void P(const Row A[])
>> >>       ^
>> >
>> > I think gcc is right to complain.
>> >
>> > Whilst the types are not compatible, that's not really the problem here.
>> > For example, you can pass an int * to a function that takes const int *
>> > and those two types are not compatible.  Argument passing is done "as if
>> > by assignment", and in an assignment the pointed-to type on the left can
>> > have extra qualifiers.  But here, the const qualifies the element type,
>> > not the pointed-to type, which is an array type.  (C has not qualified
>> > array types at all).
>> 
>> That's counter-intuitive. I thought const applied to Row.
>
> Yes, I hope (and it seems) that this gets fixed in the next revision
> of the C standard. Arrays should behave like structs with respect
> to const but currently they don't. 
>
> http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1923.htm

Interesting.  Thanks for posting that.

> Without '-pedantic' gcc will accept this, so I recommend to use
> this non-standard extension instead of adding casts which
> break type safety.

Casts can break type safety, but in this case that cast is really just
permitting a safe operation currently ruled out by the language.  It may
be that the value of -pedantic outweighs the concerns about adding what
is, after all, a safe cast.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#99848

Fromsupercat@casperkitty.com
Date2016-12-18 14:43 -0800
Message-ID<95bae933-f2e2-42bf-a949-ef1ccf55eeea@googlegroups.com>
In reply to#99836
On Sunday, December 18, 2016 at 2:11:38 PM UTC-6, Ben Bacarisse wrote:
> > Yes, I hope (and it seems) that this gets fixed in the next revision
> > of the C standard. Arrays should behave like structs with respect
> > to const but currently they don't. 
> >
> > http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1923.htm
> 
> Interesting.  Thanks for posting that.
> 
> > Without '-pedantic' gcc will accept this, so I recommend to use
> > this non-standard extension instead of adding casts which
> > break type safety.
> 
> Casts can break type safety, but in this case that cast is really just
> permitting a safe operation currently ruled out by the language.  It may
> be that the value of -pedantic outweighs the concerns about adding what
> is, after all, a safe cast.

The problem, fundamentally, is that rather that rather than allowing use
of parentheses to distinguish between "int (const foo[4][4])" and
"(int const)foo[4][5]", someone decided that qualifiers should be applied
to the variable by putting them inside the subscript expression--something
which totally fails with array type specifiers that don't include subscript
expressions, and doesn't really make sense anyhow.
 

[toc] | [prev] | [next] | [standalone]


#100495

FromTim Rentsch <txr@alumni.caltech.edu>
Date2016-12-29 13:33 -0800
Message-ID<kfnwpeiv2s0.fsf@x-alumni2.alumni.caltech.edu>
In reply to#99848
supercat@casperkitty.com writes:

> On Sunday, December 18, 2016 at 2:11:38 PM UTC-6, Ben Bacarisse wrote:
>>> Yes, I hope (and it seems) that this gets fixed in the next revision
>>> of the C standard.  Arrays should behave like structs with respect
>>> to const but currently they don't.
>>>
>>> http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1923.htm
>>
>> Interesting.  Thanks for posting that.
>>
>>> Without '-pedantic' gcc will accept this, so I recommend to use
>>> this non-standard extension instead of adding casts which
>>> break type safety.
>>
>> Casts can break type safety, but in this case that cast is really just
>> permitting a safe operation currently ruled out by the language.  It may
>> be that the value of -pedantic outweighs the concerns about adding what
>> is, after all, a safe cast.
>
> The problem, fundamentally, is that rather that rather than allowing use
> of parentheses to distinguish between "int (const foo[4][4])" and
> "(int const)foo[4][5]", someone decided that qualifiers should be applied
> to the variable by putting them inside the subscript expression--[...]

The problem, fundamentally, is that you are clueless.  That
has nothing to do with the issue being addressed here.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web