There are two source files in my program.
An array is defined in A.cpp.
// compiler: MSVC2005 SP2
// A.cpp
// defines an array of type "int [100]"
int a[100] = {3};
It is used in B.cpp.
// B.cpp
// declares an array of type "int []"
extern int a[];
int main()
{
// prints 3 correctly
cout << a[0] << endl;
return 0;
}
AFAIK, linker will raise an error if it cannot find any matched definition for a declaration if the declared identifier is used. Here, int [] and int [100] are two different types, obviously.
Why, in this case, isn’t there any link error? Is it guaranteed by the Standard that array size is trivial during matching of declaration/definition? Or it’s just implementation-specific? A quote from the Standard will be appreciated if any.
Edit: iammilind mentioned in his answer that linker can run correctly(his compiler is gcc) even if the type does NOT match between declaration and definition. Is it REQUIRED by the Standard or just a way of gcc? I guess this is a far more important issue to figure out.
In both C and C++ a declaration of an object
aof incomplete type will match the definition of objectawhere the type is complete. What you observe simply illustrates the fact that in C++ you are allowed to use incomplete types in non-defining declarations. But once you get to the definition the type must be complete.This behavior is not restricted to arrays. For example, you can declare
for a totally unknown class
X, and then, whenclass Xis already fully defined, you can definewhich will match to the above declaration.
The same thing happens with your array. Firstly you declare an object of incomplete type
and then you define it with complete type
The types here indeed are not matching. However, the C++ language never required them to match. For example, 3.9/7 explicitly states
It means that the same array object can have incomplete type initially, but acquire a complete type later on. (See also the example in 3.9/7). This doesn’t, of course, mean that you can declare
aas anintand then define it as adouble. The only type-related freedom you have here is, again, to complete an incomplete type. No more.