Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shouldn't declaration match its definition when array is involved?

Tags:

c++

arrays

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.

like image 506
Eric Z Avatar asked Jul 31 '11 04:07

Eric Z


People also ask

What is array declaration in C++?

An "array declaration" names the array and specifies the type of its elements. It can also define the number of elements in the array. A variable with array type is considered a pointer to the type of the array elements. Because constant-expression is optional, the syntax has two forms: The first form defines an array variable.

When to use a direct declaration of a variable?

You can use this form only if you previously have initialized the array, declared it as a parameter, or declared it as a reference to an array explicitly defined elsewhere in the program. In both forms, direct-declarator names the variable and can modify the variable's type.

How to refer to an individual element of an array?

To refer to an individual element of an array, use a subscript expression, as described in Postfix Operators. The two-dimensional array named matrix has 150 elements, each having float type. This is a declaration of an array of structures. This array has 100 elements; each element is a structure containing two members.

What do the brackets mean in a direct-declarator?

The brackets ( [ ]) following direct-declarator modify the declarator to an array type. Type qualifiers can appear in the declaration of an object of array type, but the qualifiers apply to the elements rather than the array itself.


2 Answers

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.

like image 60
AnT Avatar answered Sep 23 '22 10:09

AnT


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.

like image 27
6502 Avatar answered Sep 24 '22 10:09

6502