在涉及数组时,不应该声明与其定义匹配吗?

时间:2011-07-31 04:22:22

标签: c++ arrays

我的程序中有两个源文件。

数组在 A.cpp

中定义
// compiler: MSVC2005 SP2    
// A.cpp

// defines an array of type "int [100]"
int a[100] = {3};

用于 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,如果使用声明的标识符,如果找不到声明的任何匹配定义,链接器将引发错误。在这里, int [] int [100] 显然是两种不同的类型。

在这种情况下,为什么没有链接错误? 标准是否保证在声明/定义匹配期间数组大小是微不足道的?或者它只是特定于实现?如果有的话,标准的引用将会受到赞赏。

编辑: iammilind在他的回答中提到链接器可以正确运行(他的编译器是gcc)即使类型在声明和定义之间不匹配。是标准要求还是gcc的方式?我想这是一个非常重要的问题。

5 个答案:

答案 0 :(得分:7)

在C和C ++中,不完整类型的对象a的声明将匹配类型完整的对象a的定义。您观察到的只是说明了在C ++中允许在非定义声明中使用不完整类型的事实。但是一旦达到定义,类型必须完整。

此行为不限于数组。例如,您可以声明

extern class X x;

对于一个完全未知的类X,然后,当class X已经完全定义时,您可以定义

X x;

将与上述声明相匹配。

您的阵列也会发生同样的事情。首先声明一个不完整类型的对象

extern int a[];

然后用完整类型

定义它
int a[100];

这里的类型确实不匹配。但是,C ++语言从未要求它们匹配。例如,3.9 / 7明确说明

  

数组对象的声明类型可能是未知大小的数组   因此,在翻译单位的某一点上不完整   稍后完成;这两个点的数组类型(“数组的数组   未知的T“和”N T“数组的界限是不同的类型。

这意味着相同的数组对象最初可能具有不完整的类型,但稍后会获得完整的类型。 (另见3.9 / 7中的例子)。当然,这并不意味着您可以将a声明为int,然后将其定义为double。你在这里唯一与类型相关的自由是完成一个不完整的类型。没有了。

答案 1 :(得分:1)

首先,代码不应该给出任何错误。规范int a[]a[100]不同,但与之兼容(它只是不完整)。

第二个重点是,您不能指望C ++编译器/链接器为跨模块不连贯性提供错误。例如,在C ++程序中,您不能使用不同的定义将同一个类定义两次,但编译器不需要告诉您这个问题,这对程序员来说是一个负担。

如果某个实现检测到并发出此类问题的信号,那么很好,但是实现没有告诉他们任何事情,只是创建崩溃的可执行文件仍然完全符合。

答案 2 :(得分:0)

这里说“C ++允许将方括号留空[]。在这种情况下,编译器将假定数组的大小与大括号{}之间包含的值的数量相匹配”。因此,如果这个参考文献是正确的,它似乎是标准的一部分。

http://www.cplusplus.com/doc/tutorial/arrays/

答案 3 :(得分:0)

你的问题是真的。这里几乎没有问题。

当您声明两个具有相同名称的符号时;然后没有检查     来自链接器的类型/大小等。它只是解决它们和     将它们联系在一起。例如,尝试声明extern float a[];extern int a[3];它仍然有效。这就是C ++的方式     (不幸的是)设计了链接器。

所以解决方案是在头文件中声明它们,并在a.cpp和b.cpp中声明#include

答案 4 :(得分:0)

以下链接:

http://www.lysator.liu.se/c/c-faq/c-2.html

有您正在寻找的解释。