Reputation: 14515
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.
Upvotes: 8
Views: 286
Reputation: 114559
First of all that code should not give any error. The specification int a[]
is different from a[100]
but is compatible with it (it's just incomplete).
A second important point is that you cannot count on C++ compiler/linker giving errors for cross-module incoherence. For example in a C++ program you cannot have the same class defined twice with a different definition, but the compiler is not REQUIRED to tell you about this problem, it's a burden left on the programmers.
If an implementation detects and signals this kind of problem then fine, but an implementation not telling anything about them and just creating crashing executables is still perfectly compliant.
Upvotes: 1
Reputation: 320631
In both C and C++ a declaration of an object a
of incomplete type will match the definition of object a
where 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
extern class X x;
for a totally unknown class X
, and then, when class X
is already fully defined, you can define
X x;
which will match to the above declaration.
The same thing happens with your array. Firstly you declare an object of incomplete type
extern int a[];
and then you define it with complete type
int a[100];
The types here indeed are not matching. However, the C++ language never required them to match. For example, 3.9/7 explicitly states
The declared type of an array object might be an array of unknown size and therefore be incomplete at one point in a translation unit and complete later on; the array types at those two points (“array of unknown bound of T” and “array of N T”) are different types.
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 a
as an int
and then define it as a double
. The only type-related freedom you have here is, again, to complete an incomplete type. No more.
Upvotes: 7
Reputation: 38216
This following link:
http://www.lysator.liu.se/c/c-faq/c-2.html
has the explanation you are looking for.
Upvotes: 0
Reputation: 70030
Your question is genuine. Here there are few problems.
When you declare two symbols with same names; then there is no check
from linker for its type/size etc. It just resolves them and
correlate them together. For example try declaring extern float
a[];
or extern int a[3];
it will still work. This is the way C++
linker is (unfortunately) designed.
So the solution is to declare them in header file and #include
in both of a.cpp and b.cpp.
Upvotes: 0
Reputation: 90804
Here it says that "C++ allows the possibility of leaving the square brackets empty [ ]. In this case, the compiler will assume a size for the array that matches the number of values included between braces { }". So if this ref is right, it seems to be part of the standard.
http://www.cplusplus.com/doc/tutorial/arrays/
Upvotes: 0