strange warning

B

Bill Cunningham

This code looks correct to me. But the compiler issued this warning.
What's it trying to tell me?

#include <stdio.h>

int main()
{
int *p;
int a[5] = { 0 };
p = &a;
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 3));
}

p.c: In function 'main':
p.c:7:7: warning: assignment from incompatible pointer type [enabled by
default]
 
G

glen herrmannsfeldt

Bill Cunningham said:
This code looks correct to me. But the compiler issued
this warning.
(snip)

int *p;
int a[5] = { 0 };
p = &a;
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 3));
(snip)

p.c:7:7: warning: assignment from incompatible pointer type
[enabled by default]

You want:

p=a;

instead.

-- glen
 
M

Malcolm McLean

This code looks correct to me. But the compiler issued this warning.

What's it trying to tell me?

#include <stdio.h>

int main()
{
int *p;
int a[5] = { 0 };

p = &a;
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 3));
}

p.c: In function 'main':
p.c:7:7: warning: assignment from incompatible pointer type [enabled by
default]
Compiler being fussy.
If "a" is an array, "&a" and "a" mean almost the same thing. It's a quirk
of C, the "array pointer equivalence" rule which almost holds but not quite.
Take off the & and the the warning should go away and the code will
do the same thing. Silly, but that's how it works.

The compiler thinks that int a[5]; p = &a; means p should be a pointer to
5 integers, so p++ would increment the pointer by five integers instead
of one. Not something you probably want. It thinks int a[5], p = a;
means p should be a plain int *, so p++ increments the pointer by one
and moves it along to the next integer. That's what you normally do
want.
 
I

Ian Collins

Malcolm said:
This code looks correct to me. But the compiler issued this warning.

What's it trying to tell me?

#include <stdio.h>

int main()
{
int *p;
int a[5] = { 0 };

p = &a;
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 3));
}

p.c: In function 'main':
p.c:7:7: warning: assignment from incompatible pointer type [enabled by
default]
Compiler being fussy.

s/fussy/correct/
 
O

Osmium

Bill Cunningham said:
This code looks correct to me. But the compiler issued this warning.
What's it trying to tell me?

#include <stdio.h>

int main()
{
int *p;
int a[5] = { 0 };
p = &a;
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 3));
}

p.c: In function 'main':
p.c:7:7: warning: assignment from incompatible pointer type [enabled by
default]

The compiler has set up a location and agreed to let you call that location
'a'. They are telling you that a does not contain an int. Consider: If it
did contain an int, where would they put a[1]? How would they find a[1]?
In fact, a contains effectively a *pointer* to an int, not an int. That's
what they are telling you. p is of type pointer to int and a is not an int.
They want you to fix it.
 
B

Barry Schwarz

This code looks correct to me. But the compiler issued this warning.
What's it trying to tell me?

#include <stdio.h>

int main()
{
int *p;
int a[5] = { 0 };
p = &a;
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 3));
}

p.c: In function 'main':
p.c:7:7: warning: assignment from incompatible pointer type [enabled by
default]

p can only hold values of type pointer to int. The expression &a has
type pointer to array of 5 int. This type is incompatible with p
(there is no implicit conversion from int(*)[5] to int*).

If you change the expression to
p = a;
the situation changes. a is an expression with array type. Under
most conditions, such an expression is automatically converted by the
compiler the address of the first element with type pointer to element
type. In this case, the first element is a[0] which is an int so the
expression is converted to type pointer to int. This renders the
changed statement exactly equivalent to
p = &a[0];

The reason the changed statement works while your original doesn't is
because one the exceptions to the conversion rule stated above is when
the array expression is the operand of the & operator. If you are
interested in the details of the conversion rule see n1256, section
6.3.2.1-3, or the equivalent in any of the newer versions of the
standard.
 
B

Barry Schwarz

Bill Cunningham said:
This code looks correct to me. But the compiler issued this warning.
What's it trying to tell me?

#include <stdio.h>

int main()
{
int *p;
int a[5] = { 0 };
p = &a;
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 3));
}

p.c: In function 'main':
p.c:7:7: warning: assignment from incompatible pointer type [enabled by
default]

The compiler has set up a location and agreed to let you call that location
'a'. They are telling you that a does not contain an int. Consider: If it

Actually, a contains 5 int.
did contain an int, where would they put a[1]? How would they find a[1]?
In fact, a contains effectively a *pointer* to an int, not an int. That's

a does not contain any pointers at all. It contains enough space to
hold exactly 5 int and each of those int is initialized to 0.
what they are telling you. p is of type pointer to int and a is not an int.

What the error message says is p is of type pointer to int but &a is
of an incompatible type.
 
K

Keith Thompson

Malcolm McLean said:
This code looks correct to me. But the compiler issued this warning.

What's it trying to tell me?

#include <stdio.h>

int main()
{
int *p;
int a[5] = { 0 };

p = &a;
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 3));
}

p.c: In function 'main':
p.c:7:7: warning: assignment from incompatible pointer type [enabled by
default]
Compiler being fussy.

The compiler is doing what any conforming compiler is required to do:
issuing a diagnostic message for a constraint violation.

In my opinion it isn't being fussy enough; a violation like this
*should* cause the code to be rejected. But gcc often prints mere
warnings for errors like this. (Yes, a warning is sufficient as far as
the language is concerned, and yes, gcc can be made to treat it as a
fatal error with "-pedantic-errors".)
If "a" is an array, "&a" and "a" mean almost the same thing. It's a quirk
of C, the "array pointer equivalence" rule which almost holds but not quite.
Take off the & and the the warning should go away and the code will
do the same thing. Silly, but that's how it works.

Pointers to incompatible types are incompatible. Assigning a
pointer-to-array value to a pointer-to-int object is no more valid than
assigning a pointer-to-int value to a pointer-to-double object. And in
either case, if you *really* need to perform such an assignment for some
reason you can use a cast.

Do you want all pointer types to be compatible, or should the language
be sloppy only for a pointer to an array vs. a pointer to an element of
the array?
The compiler thinks that int a[5]; p = &a; means p should be a pointer to
5 integers, so p++ would increment the pointer by five integers instead
of one. Not something you probably want. It thinks int a[5], p = a;
means p should be a plain int *, so p++ increments the pointer by one
and moves it along to the next integer. That's what you normally do
want.

In both cases, what the compiler "thinks" is simply what the language
specifies.
 
K

Keith Thompson

Osmium said:
Bill Cunningham said:
This code looks correct to me. But the compiler issued this warning.
What's it trying to tell me?

#include <stdio.h>

int main()
{
int *p;
int a[5] = { 0 };
p = &a;
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 3));
}

p.c: In function 'main':
p.c:7:7: warning: assignment from incompatible pointer type [enabled by
default]

The compiler has set up a location and agreed to let you call that location
'a'. They are telling you that a does not contain an int. Consider: If it
did contain an int, where would they put a[1]? How would they find a[1]?

Right so far.
In fact, a contains effectively a *pointer* to an int, not an int. That's
what they are telling you. p is of type pointer to int and a is not an int.
They want you to fix it.

Was that a typo? p is a pointer to an int. a is an array.
 
M

Malcolm McLean

Do you want all pointer types to be compatible, or should the language
be sloppy only for a pointer to an array vs. a pointer to an element of
the array?
The language should tighten up the distinction between a buffer and
an array. A buffer is a region of memory which may or may not contain
data, and typically has a few unused bytes at the end. An array is
a set of data that can be indexed in O constant time by an integer
subscript.
C arrays should obviously only allow subscripts from 0 to N-1 and
with no facilities for gaps or sparse arrays. There are serious questions
about how to best handle multi-dimensional arrays. Until those are
answered, it's hard to say what sorts of pointer conversions should
be considered "sloppy".
 
I

Ian Collins

Malcolm said:
The language should tighten up the distinction between a buffer and
an array.

There isn't anything to tighten up, C doesn't have a buffer type. An
array is a type and a pointer to an array is a pointer to an object of
that type.
A buffer is a region of memory which may or may not contain
data, and typically has a few unused bytes at the end. An array is
a set of data that can be indexed in O constant time by an integer
subscript.

Is it now.
C arrays should obviously only allow subscripts from 0 to N-1 and
with no facilities for gaps or sparse arrays. There are serious questions
about how to best handle multi-dimensional arrays.

Are there?
Until those are
answered, it's hard to say what sorts of pointer conversions should
be considered "sloppy".

No it isn't. A pointer to one type is distinct from a pointer to
another type.
 
M

Malcolm McLean

Malcolm McLean wrote:

There isn't anything to tighten up, C doesn't have a buffer type. An
array is a type and a pointer to an array is a pointer to an object of
that type.
void *ptr;
size_t sz = 123;
ptr = malloc(sz);

will get you a buffer of 123 bytes. It's not an array, and in fact ptr[0] = x;
is illegal.
However

unsigned char buff[123];

is almost certainly a drop-in replacement for the above code, it's
probably also a buffer. But we can't be sure, maybe it's really an array
of 123 bytes which will be initialised in the next few lines.
Are there?
Yes. Images are inherently 2D, but it doesn't usually make sense to hardcode
their dimensions at runtime. On the other hand filters for image processing
usually do have dimensions known at runtime, and it makes sense to code
4x4 or above filters in subroutines generically, but 3x3 filters really
you don't want to pass filter dimensions to a generic subroutine. So we've
got three types of 2D array, for a simple image processing program.

Then what does the syntax

bezierpatch[j] = x;

actually mean? Is bezierpatch a matrix, or a ragged array accessed through
a double pointer? I don't say this is a fatal flaw, but it's an undesireable
feature of the syntax.
No it isn't. A pointer to one type is distinct from a pointer to
another type.
No, because we can't use an int (*ptr)[5] to manipulate the data elements,
we need to derive an int * from it at some point. I was going to say
you can't access the elements, but of course you can, but it's contorted
and no-one sensible would write C that way.
 
I

Ian Collins

Malcolm said:
Malcolm McLean wrote:

There isn't anything to tighten up, C doesn't have a buffer type. An
array is a type and a pointer to an array is a pointer to an object of
that type.
void *ptr;
size_t sz = 123;
ptr = malloc(sz);

will get you a buffer of 123 bytes. It's not an array, and in fact ptr[0] = x;
is illegal.
Eh?

However

unsigned char buff[123];

is almost certainly a drop-in replacement for the above code, it's
probably also a buffer. But we can't be sure, maybe it's really an array
of 123 bytes which will be initialised in the next few lines.

Maybe its is, but as I said, the language does not make any such
distinction.
Yes. Images are inherently 2D, but it doesn't usually make sense to hardcode
their dimensions at runtime. On the other hand filters for image processing
usually do have dimensions known at runtime, and it makes sense to code
4x4 or above filters in subroutines generically, but 3x3 filters really
you don't want to pass filter dimensions to a generic subroutine. So we've
got three types of 2D array, for a simple image processing program.

If the function is generic, that you have to pass the dimensions one way
or another.
Then what does the syntax

bezierpatch[j] = x;

actually mean? Is bezierpatch a matrix, or a ragged array accessed through
a double pointer? I don't say this is a fatal flaw, but it's an undesireable
feature of the syntax.


How would your clear it up?
No it isn't. A pointer to one type is distinct from a pointer to
another type.
No, because we can't use an int (*ptr)[5] to manipulate the data elements,
we need to derive an int * from it at some point.

How is that relevant? There may be an issues with C's inability to copy
arrays, but an array is still a distinct type. For example, this will
cause a diagnostic:

typedef int (FiveInts)[5];

void f5( FiveInts* p );

int main(void)
{
int a[]={10,20,30,40,50};

f5(&a);

int b[]={10,20,30,40,50,60};

f5(&b);
}
 
B

BartC

Then what does the syntax

bezierpatch[j] = x;

actually mean? Is bezierpatch a matrix, or a ragged array accessed through
a double pointer? I don't say this is a fatal flaw, but it's an
undesireable
feature of the syntax.


You've probably hit on one of the few unique features of C that other
languages might want to copy.

Sometimes it's good to hide the dereferences likes this (you can change the
implementation of bezierpatch between and arrays and pointers to arrays, and
that code will still work.)

But if you did want to show the dereferences explicitly, I don't think the
language stops you doing that. However the prefix nature of '*' and its
precedence makes for ugly syntax:

(*(*bezierpatch))[j]) = x;

(Or something like those lines.)

(A postfix version of * would give you the more readable:

bezierpath**[j] = x;

although that looks too much like multiply if you stay with '*')
 
J

jacob navia

Le 10/05/2014 13:16, Richard a écrit :
10/10

Genius.

It'll have the regs panting : so many assumptions and misuses of what
"may not be a memory address" or how big a char is AND it brings arrays
in too. I take my hat off to whoever Bill really is. I can hardly bare
to read the insufferably pompous answers......

Yes... I agree with that, the answers are in the pure style of the
"regs": but I missed some citations of the verses of the bible, oh
pardon me, the holy standard.
 
O

Osmium

Keith Thompson said:
Osmium said:
Bill Cunningham said:
This code looks correct to me. But the compiler issued this warning.
What's it trying to tell me?

#include <stdio.h>

int main()
{
int *p;
int a[5] = { 0 };
p = &a;
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 3));
}

p.c: In function 'main':
p.c:7:7: warning: assignment from incompatible pointer type [enabled by
default]

The compiler has set up a location and agreed to let you call that
location
'a'. They are telling you that a does not contain an int. Consider: If
it
did contain an int, where would they put a[1]? How would they find a[1]?

Right so far.
In fact, a contains effectively a *pointer* to an int, not an int.
That's
what they are telling you. p is of type pointer to int and a is not an
int.
They want you to fix it.

Was that a typo? p is a pointer to an int. a is an array.

No, I meant what I said. I am not particularly interested in what the
standard says and, in fact, I'm appalled that so many people (10 or 20)
think a language standard can be so interesting. I look at the end result
of all these shenanigans.

In my view, C does not *have* arrays. They go through some sophistry to
make it look like they have arrays, and they use the word "array", but what
they actually have is sophistry. An array has, for example, a *size*. The
thing C has is without bounds. That's not an array. Should you not be able
to set one array to the value of another with the same characteristics?
That is b = a? No, you can't do that in C.

If a was an array Bill should be able to tell an independently compiled
function that a was an array. There is no such way. Such a function can be
satisfied by a parameter that is an ordinary, *indistinguishable* pointer.
What happened to the array? The gurus say it transmogrified or some such.
I say it never existed in the first place. it was all imaginary.

When C sees
int a[10];
it goes into a little dance. It sets aside room for 10 ints in one place
and in another place it creates a variable named 'a'. They set a to point
at the first int in the space set aside. Bill's problem originates with the
variable named 'a'. Thus my answer to him.

Troll score:
[0/10]
Bills confusion is simply the result you get when you misuse words that
already had a well established meaning.
 
B

Ben Bacarisse

Osmium said:
In my view, C does not *have* arrays. They go through some sophistry to
make it look like they have arrays, and they use the word "array", but what
they actually have is sophistry. An array has, for example, a *size*. The
thing C has is without bounds.

int ar[4];

has a size. Is it not, then, an array? A pointer to a row of an array
is incremented to point to the next row:

int m[4][4];
int (*rp)[4] = &m[0];
...
rp++; // move to the next row

If C has no arrays, why does a pointer to an array move in units of what
appears to be the array size?

In my view, it's better to think of C as having second class arrays with
some rather peculiar rules.

<snip>
 
K

Kenny McCormack

Ben Bacarisse said:
In my view, it's better to think of C as having second class arrays with
some rather peculiar rules.

You are, of course, entitled to that view.

However, others of us see the same set of facts and conclude more simply
that C just doesn't have arrays (in the sense of that term that we are used
to). It is probably safe to say that C has "C arrays".

With the usual understanding that if you have to qualify a thing, then it
is understood that the thing you're describing is not really an instance of
the larger class of things. It's just sort of *like* an instance of the
larger class.
 
S

Stefan Ram

However, others of us see the same set of facts and conclude more simply
that C just doesn't have arrays (in the sense of that term that we are used
to).

What programming language, then, has formed this what your
brain is »used to«?

»15.03.08
array
An aggregate that is an instance of an array type and
each element or appropriate group of elements in which
may be referenced randomly and independently of the others.«

ISO/IEC 2382-15, Information technology -- Vocabulary --
Part 15 Programming Languages
 
B

Bill Cunningham

glen herrmannsfeldt said:
Bill Cunningham said:
This code looks correct to me. But the compiler issued
this warning.
(snip)

int *p;
int a[5] = { 0 };
p = &a;
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 3));
(snip)

p.c:7:7: warning: assignment from incompatible pointer type
[enabled by default]

You want:

p=a;

instead.

So much of what has been said in this thread so far is over my head. I
hope someone is learning something. But I see what you're saying as in p=a;
But can you maybe exaplin to me in simpler terms that what the regualr
poster C programmers are saying? What is meant by incompatible type? I think
the pointer variable type is int or pointer to int. What does the compiler
think a[] is ? Maybe another pointer? Sorry I'm not not getting what they're
saying here.

Bill
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top