Consider the following code (it came about as a result of this discussion):
#include
void foo(int (*p)[]) { // Argument has incompl
void foo(int (*p)[])
{
printf("%d\n", (*p)[1]);
printf("%d\n", p[0][1]); // Line 5
}
Here, p
is a pointer to an array of an unspecified number of int
s. *p
accesses that array, so (*p)[1]
is the 2nd element in the array.
p[n]
adds p and n times the size of the pointed-to array, which is unknown. Even before considering the [1]
, it's broken. It's true that zero times anything is still 0, but the compiler's obviously checking the validity of all the terms without short-circuiting as soon as it sees zero. So...
So it's unhappy with the expression p[0], but it's happy with *p, even though these should (in theory) be equivalent.
As explained, they're clearly not equivalent... think of p[0]
as p + 0 * sizeof *p
and it's obvious why....
For "bonus" points: Can anyone confirm that MSVC 2010 is in error when it rejects line 10 with the following message? 1>\prog.c(10): warning C4048: different array subscripts : 'int ()[]' and 'int ()[3]'
Visual C++ (and other compilers) are free to warn about things that they think aren't good practice, things that have been found empirically to be often erroneous, or things the compiler writers just had an irrational distrust of, even if they're entirely legal re the Standard.... Examples that may be familiar include "comparing signed and unsigned" and "assignment within a conditional (suggest surrounding with extra parentheses)"