我的程序中有两个源文件.
数组在A.cpp中定义.
// compiler: MSVC2005 SP2
// A.cpp
// defines an array of type "int [100]"
int a[100] = {3};
Run Code Online (Sandbox Code Playgroud)
它用于B.cpp.
// B.cpp
// declares an array of type "int []"
extern int a[];
int main()
{
// prints 3 correctly
cout << a[0] << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
AFAIK,如果使用声明的标识符,如果找不到声明的任何匹配定义,则链接器将引发错误.这里,int []和int [100]显然是两种不同的类型.
在这种情况下,为什么没有链接错误?标准是否保证在声明/定义匹配期间数组大小是微不足道的?或者它只是特定于实现?如果有的话,将赞赏标准的引用.
编辑: iammilind在他的回答中提到链接器可以正确运行(他的编译器是gcc),即使声明和定义之间的类型不匹配.是标准要求还是gcc的方式?我想这是一个非常重要的问题.
在C和C++中a,不完整类型的对象的声明将匹配a类型完整的对象的定义.您观察到的只是说明了在C++中允许在非定义声明中使用不完整类型的事实.但是一旦达到定义,类型必须完整.
此行为不限于数组.例如,您可以声明
extern class X x;
Run Code Online (Sandbox Code Playgroud)
对于一个完全未知的类X,然后,当class X已经完全定义时,您可以定义
X x;
Run Code Online (Sandbox Code Playgroud)
这将符合上述声明.
您的阵列也会发生同样的事情.首先声明一个不完整类型的对象
extern int a[];
Run Code Online (Sandbox Code Playgroud)
然后用完整的类型定义它
int a[100];
Run Code Online (Sandbox Code Playgroud)
这里的类型确实不匹配.但是,C++语言从未要求它们匹配.例如,3.9/7明确说明
声明的数组对象类型可能是一个未知大小的数组,因此在翻译单元中的某一点不完整,稍后会完成; 这两个点的数组类型("T的未知边界数组"和"NT数组")是不同的类型.
这意味着同一个数组对象最初可能具有不完整的类型,但稍后会获得完整的类型.(另见3.9/7中的例子).当然,这并不意味着你可以声明a为a int然后将其定义为a double.你在这里唯一与类型相关的自由是完成一个不完整的类型.不再.