strange warning

M

Malcolm McLean

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.

int x[5] + { 1, 2, 3, 4, 5 };

declares an array of 5 integers. Everyone from any programming background
whatsoever would quickly understand that.
We can get the number of integers by in the array with the sizeof() operator.
But very few people would do that. If the x is in scope, the 5 is in the same
line, and you might as well use it directly, #defining it if you don't
like magic numbers.
Then fixed size arrays aren't all that useful. Most real algorithms work
on variable length arrays. C doesn't tie the length to the buffer,
the programmer has to keep track of it in the program logic flow.
So in that sense, C doesn't have arrays, it doesn't have a tight distinction
between an array and a buffer.
 
K

Keith Thompson

Malcolm McLean 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.
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.

I'm still not at all sure what distinction you're making, or how you
think that distinction should be expressed in the language syntax.

The way C handles arrays, pointers, and so forth is not exactly clean,
but it's incredibly flexible.

I have no doubt that there are cleaner ways to do this than what C has
evolved into over the years -- and if you can describe such a way in
concrete terms, that could be interesting. If you can come up with
something that could be cleanly added to C without breaking existing
code, that would be fascinating.
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.


Strictly speaking, a multidimensional array is nothing more or less than
an array of arrays. But C provides multiple ways to implement data
structures that act like multidimensional arrays.

Is that a problem? If so, how would you solve it?
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.

Yes, a pointer to one type is really is distinct from a pointer to
another type, and it's absurd to claim otherwise. Can you clarify the
point you're trying to make about accessing the data elements?
 
B

Ben Bacarisse

You are, of course, entitled to that view.

However,

That sounds like you are about to disagree, but...
[...] 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".

.... you then say pretty much what I did, only in a rather confused way.
(C does not have them (as you understand them) but it has them if we
qualify the term). My "second class" (a technical term) and my "with
some rather peculiar rules" are just more expansive versions of your
less helpful qualification: "C".

But, yes, let's agree that C has C arrays: that int a[4]; declares a C
array and that int (*ap)[4]; makes ap a pointer to a C array. And,
since this is comp.lang.c, we could also agree to drop "C" and take it
as read.
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.

Eh? Fortran has Fortran Arrays, Python has Python arrays, Perl as Perl
arrays... and C has C arrays. All really are instances of the larger
class of arrays, unless you make a case for the differences being such
as to exclude them from the class (in which case, you should not really
use even a qualified name for them).
 
G

glen herrmannsfeldt

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

(snip, then I wrote)
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.

I am not sure I can say it all that much better, but consider
that array a can be referenced as a, and pointer p can be
referenced as p, so the assignment p=a makes more sense than
the assignment p=&a;

Even though it isn't quite right, especially in the case of sizeof,
I think of a as a pointer to int constant, and so should not use &.

-- glen
 
K

Keith Thompson

Osmium said:
Keith Thompson said:
Osmium said:
"Bill Cunningham" wrote: [...]
int *p;
int a[5] = { 0 }; [...]
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.

Nonsense.

The standard defines the language. If you refuse to understand
what it says, there's not much else to say, other than to wonder
what you're doing here.

You can probably do some amount of C programming without
understanding how C pointers an arrays work, but I doubt that you
can get very far.

I won't bother to explain again how C arrays work. If you're
interested, I recommend section 6 of the comp.lang.c FAQ,
<http://www.c-faq.com/>. If you're not, that's fine, but you might
consider leaving this discussion to those of us who are interested.

[...]
Bills confusion is simply the result you get when you misuse words that
already had a well established meaning.

Standards almost always use English words with meanings that are
more precise than, and sometimes not entirely consistent with, the
way they're used in English. The alternative would be to invent
new words for specific concepts, but I think that would just make
it more difficult to understand. Do you have a better way to define
a programming language?
 
G

glen herrmannsfeldt

(snip)
I'm still not at all sure what distinction you're making, or how you
think that distinction should be expressed in the language syntax.
(snip)

Strictly speaking, a multidimensional array is nothing more or less than
an array of arrays. But C provides multiple ways to implement data
structures that act like multidimensional arrays.
Is that a problem? If so, how would you solve it?

I like the way Java multidimensional arrays work.

You can say:

int x[][]; (or int[][] x), and then

x=new int[10][10];

At which point it allocates a 10 element array of arrays,
and then 10 arrays of int. The confusion that C has with

int y[10][10], z[20][20];

passed to a function, doesn't occur in Java.

It is fairly rare, but you can separately allocate the arrays
in Java:

x=new int[10][];
x[3]=new int[13];

and make the subarrays different length.

-- glen
 
I

Ian Collins

glen said:
(snip)
int *p;
int a[5] = { 0 };
p = &a;

(snip, then I wrote)
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.

I am not sure I can say it all that much better, but consider
that array a can be referenced as a, and pointer p can be
referenced as p, so the assignment p=a makes more sense than
the assignment p=&a;


Just let a compiler provide the explanation:

c99 b.c
"b.c", line 7: warning: assignment type mismatch:
pointer to int "=" pointer to array[5] of int
 
K

Keith Thompson

Malcolm McLean said:
int x[5] + { 1, 2, 3, 4, 5 };

declares an array of 5 integers. Everyone from any programming background
whatsoever would quickly understand that.
Agreed.

We can get the number of integers by in the array with the sizeof() operator.
But very few people would do that.

People do that all the time:

#define ARRAY_LENGTH(arr) (sizeof (arr) / sizeof (arr)[0])
 
B

Barry Schwarz

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

Two types are compatible if there is an implicit conversion from one
to the other. For example, from int to long, long to int, int to
double, pointer to void to any other pointer type.

Two types are incompatible if the implicit conversion does not exist.
In your case, the type of p is pointer to int and the type of &a is
pointer to array of 5 int. There is no implicit conversion between
these types..
the pointer variable type is int or pointer to int. What does the compiler

The type of a pointer variable is never int. It is always pointer to
something. In your case, p has type pointer to int.
think a[] is ? Maybe another pointer? Sorry I'm not not getting what they're
saying here.

The meaning of a[] is context dependent.

In a definition such as
int a[] = {1,2,3,4,5};
it means a is an array whose number of elements will be determined by
the number of initializers provided.

In a function declaration such as
void func(int a[]);
it means that the parameter a received from the calling function is in
fact a pointer to int and the function declaration is exactly
equivalent to
void func(int *a);

Since expression a[] never appears in your code, I don't know what you
mean by the question or why you are bringing up something completely
extraneous.
 
K

Keith Thompson

Barry Schwarz said:
Two types are compatible if there is an implicit conversion from one
to the other. For example, from int to long, long to int, int to
double, pointer to void to any other pointer type.

A quibble: The C standard defines the term "compatible types",
and the definition is much more strict than that. The definition
is in N1570 6.2.7p1, with references to several other sections.
To summarize:

- A type is compatible with itself (this includes typedefs, of course).
- An enum type is compatible with some integer type.
- Two pointer types are compatible if they're identically qualified
pointers to compatible types.
- Two array types are compatible if they have compatible element types
and have identical constant size, or if one of the types doesn't have
a constant size (the latter case can cause undefined behavior if the
sizes don't match).
- Two function types are compatible if they have compatible return and
parameter types, plus some other rules if one type has an old-style
non-prototype declaration.

int and long are definitely not compatible types. Incompatible types
often have implicit conversions, but pointers to incompatible types do
not (aside from the special case of void*).

There doesn't seem to be a term in the standard for types that have an
implicit conversion. Perhaps "assignment-compatible" would be
reasonable.

[...]
 
J

James Kuyper

On 05/10/2014 05:16 PM, Barry Schwarz wrote:
....
Two types are compatible if there is an implicit conversion from one
to the other. For example, from int to long, long to int, int to
double, pointer to void to any other pointer type.

Compatible scalar types can be implicitly converted to each other, but
most implicit conversions apply to types that are not compatible with
each other. Also, aggregate types can be compatible, but cannot be
implicitly converted.

The standard says that two types are compatible only in certain specific
cases:

(6.2.7p1):
"Two types have compatible type if their types are the same.
Additional rules for determining whether two types are compatible are
described in 6.7.2 for type specifiers, in 6.7.3 for type qualifiers,
and in 6.7.6 for declarators.55) Moreover two structure, union, or
enumerated types declared in separate translation units are compatible
if their tags and members satisfy the following requirements: If one is
declared with a tag, the other shall be declared with the same tag. If
both are completed anywhere within their respective translation units,
then the following additional requirements apply: there shall be a
one-to-one correspondence between their members such that each pair of
corresponding members are declared with compatible types; if one member
of the pair is declared with an alignment specifier, the other is
declared with an equivalent alignment specifier; and if one member of
the pair is declared with a name, the other is declared with the same
name. For two structures, corresponding members shall be declared in the
same order. For two structures or unions, corresponding bit-fields shall
have the same widths. For two enumerations, corresponding members shall
have the same values."

Note that "two structure, union, or enumerated types declared in" the
same translation unit are NOT compatible, not even if they meet all of
those other requirements.

Here are the "additional rules" referred to by that clause, in their
entirety:

6.7.2.2p4:
"Each enumerated type shall be compatible with char, a signed integer
type, or an unsigned integer type. The choice of type is
implementation-defined, ..."

6.7.3p10:
"For two qualified types to be compatible, both shall have the
identically qualified version of a compatible type ..."

6.7.6.1p2:
"For two pointer types to be compatible, both shall be identically
qualified and both shall be pointers to compatible types."

6.7.6.2p10: "For two array types to be compatible, both shall have
compatible element types, and if both size specifiers are present, and
are integer constant expressions, then both size specifiers shall have
the same constant value."

The fact that types with differing qualifiers (and pointers to those
types) are NOT compatible is the key thing that renders invalid a lot of
code that does things with qualified types that should NOT be done. For
instance, declaring a variable with 'const' in one translation unit, and
without it in another.

The standard never defines directly what "compatible type" means. It
only defines a single general case (same type) and a small number of
special cases. It then goes on, in a variety of places, to require that
under certain circumstances, it is a constraint violation or undefined
behavior for two types to be incompatible.

From what the standard does say, you can derive a few things that the
standard does not say, at least not directly: compatible types are
required to be implemented in essentially the same way, even if they're
not the same type. At a minimum, they have to have the same
representation, alignment requirement, and must be treated equivalently
as function arguments or function return values.
 
B

Bill Cunningham

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.

I will look. I can't guarantee understanding; but I will look and to my
knowledge n1256 is the newest or maybe a n1257 exists. I can't remember
which.

Bill
 
B

Bill Cunningham

I am not sure I can say it all that much better, but consider
that array a can be referenced as a, and pointer p can be
referenced as p, so the assignment p=a makes more sense than
the assignment p=&a;

Even though it isn't quite right, especially in the case of sizeof,
I think of a as a pointer to int constant, and so should not use &.


Ok so then is at least part of it size which would make the compiler
warn of differing types? I understand I am dealing with an array of ints.
The point is of type int, I guess just one int. malloc() could've been used
here...

malloc(5*sizeof(int)); // But that's usually for dynamic allocation. I did
want the more "static" type of memory storage of an array. a can be
considered a pointer in a sense too. So to assign a pointer to a pointer as
p=a makes sense that way. More so than p=&a.


Bill
 
M

Malcolm McLean

Nonsense. Pure and utter tosh. Fixed length arrays are used all over the
shop.
What you're probably thinking is that, for many C programs, data is
incorporated into the program in arrays at compile time. For example the
Baby X resource compiler does that. However whilst the size of an
Baby X resource-compiler generated array is known at compile time,
it's not generally known at program write time.

Most algorithms which are defined for an array of N items are defined for
all values of N, or for all values except a few degenerate cases like N = 0,
or N = 1. There are exceptions, for example the cross-product. The dot product
is defined for all N, however. A chess-playing function probably can't
meanigfully operate on a board that isn't 8x8. However a snakes and ladders
function probably shouldn't be hard-coded to boards 10x10.
 
B

BartC

Nonsense.

He has a point. C's implementation of arrays is somewhat lightweight.

For example, it doesn't really have proper array indexing: A is almost
universal in selecting element i of array A, but in C it is syntactic sugar
for *(A+i); A here is really a pointer to a type which matches the element
type of what would be the array.

Other languages way well do exactly the same behind the scenes, but C does
it openly (but in doing so, conflates arrays and pointers in a way that
affects the integrity of the type system: see the 'Using char[] as function
argument ... ' thread).

And a C array doesn't officially have a length that you can interrogate,
even though you used that same length to declare it! You have to calculate
it indirectly by some arithmetic involving the byte-size of the whole array
object, and the byte-size of one of its elements, as you demonstrated in
another post.
 
B

BartC

Richard said:
Nonsense. Pure and utter tosh. Fixed length arrays are used all over the
shop.

I think he's right. Fixed length arrays have been only a small part of any
sizeable program I've written.

They might be used for small buffers, eg. char[100] to hold the result of
some decimal expansion of a number for example.

Or to construct data types where the size is an integral part: double[4][4]
for a matrix for example; I wouldn't really consider that as an array type,
but as a matrix type.

Proper arrays tend to be large and/or dynamic, and here it is unusual to use
a fixed size for them. Certainly when you pass an T[] array - fixed size or
otherwise - to a function taking a T* parameter, the fixed length aspect is
lost.
 
I

Ike Naar

int x[5] + { 1, 2, 3, 4, 5 };

declares an array of 5 integers. Everyone from any programming background
whatsoever would quickly understand that.

Everyone from a programming background would also understand that you
have had a problem operating your shift key ;-)
 
J

James Kuyper

I think he's right. Fixed length arrays have been only a small part of any
sizeable program I've written.

The overwhelming majority of the arrays in the code I work on have a
fixed size, including all of the largest ones. For instance, in programs
designed for processing MODIS data, the largest arrays tend to contain
one dimension whose length is the number of detectors in a given band
(10, 20, or 40 detectors, depending upon the band), and another whose
length is the number of frames of of data collected during a single
mirror scan (1354, 2708, or 5416 columns, with the same band
dependence). All of those numbers were fixed when the MODIS instrument
was first designed and built, and cannot be changed except by designing
and building a new instrument. It is possible for the instrument to
collect less than the maximum number of frames of data during a given
scan, but that doesn't happen often enough to justify making that
dimension variable. Even if the code gets ported to a new, similar
instrument with different characteristics (which has, in fact,
happened), that would just be a matter of changing some #defines, it is
not a change that could ever occur at run time.

I'm not saying that this is typical. I'm pointing out that there's a
wide ranged of variation. Any general claim that "fixed size arrays
aren't all that useful" is doomed to fail in specific cases, because
it's built upon experience with one particular kind of computer programming.
 
B

Bill Cunningham

A quibble: The C standard defines the term "compatible types",
and the definition is much more strict than that. The definition
is in N1570 6.2.7p1, with references to several other sections.
[snip]

n1570 which I looked up is the C11 standard. I do not know a thing about
that and my gcc doesn't seem to have any new possible C11 headers that I
see. I must conclude that gcc isn't C11 compliant. I am just staring to use
/some/ of C99.

Bill
 
I

Ian Collins

Malcolm said:
What you're probably thinking is that, for many C programs, data is
incorporated into the program in arrays at compile time. For example the
Baby X resource compiler does that. However whilst the size of an
Baby X resource-compiler generated array is known at compile time,
it's not generally known at program write time.

Most algorithms which are defined for an array of N items are defined for
all values of N, or for all values except a few degenerate cases like N = 0,
or N = 1. There are exceptions, for example the cross-product. The dot product
is defined for all N, however. A chess-playing function probably can't
meanigfully operate on a board that isn't 8x8. However a snakes and ladders
function probably shouldn't be hard-coded to boards 10x10.

You appear to live in the land of the abstract. For those of us who
live in the real world, fixed length arrays are a normal part of our
programming life.
 

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
474,076
Messages
2,570,565
Members
47,201
Latest member
IvyTeeter

Latest Threads

Top