GCC链接时externs的错误使用?

3

我对gcc比较陌生,目前使用的是“gcc (tdm-1) 5.1.0”版本。无意中遇到了一个非常奇特的情况。我将问题缩小到一个非常小的可重复示例...

main.cpp

extern int g;

int main(){
    return g;
}

someOtherFile.cpp

#include<windows.h>

RECT g;

我用以下内容编译

gcc -c someOtherFile.cpp
gcc main.cpp someOtherFile.o

这将会无误地链接。

我是否遗漏了什么,为什么允许进行此链接?


extern变量在其他地方被定义,因此gcc会搜索定义并在.o文件中找到它。 - ForceBru
我的担忧是关于变量g的类型。g被定义为RECT,但声明为int。这应该会抛出一个错误,对吗? - Dave
也许 RECT 只是 int 的别名?你应该查找该类型的定义。 - ForceBru
请返回已翻译的文本:定义在此处... https://msdn.microsoft.com/zh-cn/library/windows/desktop/dd162897(v=vs.85).aspx - Dave
1
使用g++编译器也可以无错误链接。我本来期望会出现错误,难道是编译器有问题吗? - Dave
2个回答

4

3.5/10:

在进行类型调整之后(在此期间,typedefs(7.1.3)被替换为其定义),指向给定变量或函数的所有声明所指定的类型必须相同,除了数组对象的声明可以指定不同的数组类型,这些类型之间只有主要数组维数的存在或缺失不同(8.3.4)。对于类型标识的这个规则的违反不需要进行诊断。

最后一句话的意思是编译器和链接器不需要为您提供错误消息。 它是您的职责使其正确。


1
啊,好的。我习惯使用微软编译器,它会抛出一个错误。 感谢您引用规范。 - Dave

0

在C++中,由于g的类型在main.cpp和someOtherFile.cpp之间不匹配,因此它无法链接。您必须在someOtherFile.cpp中拥有int g或者在main.cpp中拥有extern RECT g;

在C中,这将编译和链接,但在C++中不行。 要以C++编译和链接,请使用以下命令:

g++ -c someOtherFile.cpp
g++ -c main.cpp
g++ main.o someOtherFile.o -o test

或者,您可以使用函数来实现:

main.cpp

int g();

int main{
    return g();
}

someOtherFile.cpp

#include<windows.h>

RECT r;
int g()
{
    return (int)r;
}

显然不推荐这样做(因为将RECT转换为int没有多大意义),但这与您尝试做的事情类似。

someOtherFile.cpp中的变量g与在main.cpp中声明的其他extern int g无关。实际上,int g根本没有定义在任何地方,因此链接器最终会因此失败。

显然,这实际上可以通过g++编译和链接,而微软链接器将在此类错误上出错。


哦,你应该使用g++进行编译和链接。这段代码可以作为C语言编译并链接。 - Pavel P
正如我所说,我也可以使用g++进行编译和链接,难道编译器出了问题吗? - Dave
是的,将两个文件使用g++编译,就像示例一样,并进行链接。 - Dave
1
我知道。这让我感到非常惊讶。你可以使用它来转换任何东西。无论是否在规范中,我认为这相当糟糕,因为链接器具有错误或警告所需的信息。 - Dave
@Dave 不,我的意思是如果你有一些OtherFile.cpp文件和RECT g;,另一个是SomeOtherFile2.cpp文件和float g,但不确定是否符合标准,而这对于MS编译器肯定没问题。 - Pavel P
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接