Here's an example that involves a relatively rare, but sometimes encountered mistake
void foo(struct S *v);
struct S {
int i;
};
int main() {
struct S *p = 0;
foo(p); // ERROR: incompatible pointer types
}
The above code is ill-formed (to borrow a C++ term), because struct S
is not yet known at the point of declaration of foo
. For this reason struct S
inside the prototype of foo
is interpreted as a forward declaration of a new type. It has function prototype scope. It goes out of scope once the prototype ends. This means that declaration of struct S
inside the foo
's prototype is completely unrelated to the declaration of struct S
that follows it. These are two different types. Pointer p
inside main
is not compatible to the parameter type of foo
. The code is ill-formed.
Note that if you swap the declaration of struct S
and the prototype of foo
, the declaration of struct S
inside thew prototype is no longer a forward declaration. It is assumed to refer to the previously declared struct S
. The code becomes correct.