2010-03-27 39 views
5

以下两个声明有什么区别?我认为它们是相当的,但第一个样本有效,第二个样本没有。我的意思是它编译并运行,但位图显示代码显示为空白。我还没有穿过它,但我错过了明显的东西? GUI_BITMAP是描述位图的简单结构。这是VC++ 2005,但我认为它也在VC++ 2008中失败。抓我的头就这一个...C++中的extern关键字问题

示例1:

extern "C" const GUI_BITMAP bmkeyA_cap_active; 
extern "C" const GUI_BITMAP bmkeyA_cap_inactive; 

示例2:

extern "C" 
{ 
    const GUI_BITMAP bmkeyA_cap_active; 
    const GUI_BITMAP bmkeyA_cap_inactive; 
}; 

编辑:更多的探索表明,第二个例子创建结构,而第一个是指外部结构。第二个示例应该无法链接,因为在全局范围内有两个具有相同名称的变量。但它不会,它会发送一个零填充结构到放弃的显示代码。嗯.....

编辑2:通过另一个编译器(IAR)运行相同的代码实际上无法在示例2上编译,并且出现关于缺少默认构造函数的错误。所以我猜测有关于“extern”关键字,结构和C++的细节我没有得到。如果外部区域中的东西是功能,那么这两个样本是相同的?

回答

3

您的链接器可能会默默解决背后的重复符号。您可能会从供应商那里获得静态库,并且必须将它们与您的程序链接起来 - 如果您有两个这样的库并且它们都定义了一个通用符号,那么该解决方案的解决方案是什么?链接器会解决这个问题,选择一个或另一个定义,然后让你处理这个影响。你如何处理你的应用程序的链接阶段?如果直接链接.o文件,而不是在链接最终应用程序之前将其放入中间库,则可能会获得更好的结果。

的ARM文档This page描述的问题很好 - 我希望类似的行为是发生在你的情况:

在不同库对象一个符号的多个定义不一定检测。一旦链接器为符号找到合适的定义,就停止寻找其他符号。假设包含重复符号的对象因其他原因未加载,则不会发生错误。这是有意的,在某些情况下特别有用。

编辑:更多的搜索已止跌回升,这个问题是因为违反了“One Definition Rule”造成的,并因此不需要编译器/连接器,通知您的问题。这使您的问题成为this one的重复。

+0

感谢您的回复,但这里没有使用库对象,这全是我的代码,它是C和C++的混合体。我的原始问题仍然存在 - 样本1和样本2有什么区别 - 我认为它们应该生成完全相同的代码?如果事情是功能而不是结构 - 它们是相同的东西,对吧? – Jeff 2010-03-27 13:44:42

+1

@杰夫,你的问题的快速答案是,不,这两个不一样,这就是为什么你看到问题。在第二种情况下,您只是修改'{}'中的语句以使用C的链接约定。在第一个例子中,你正在做* plus *表示变量是在其他地方声明的。 http://msdn.microsoft.com/en-us/library/0603949d(VS.80).aspx – 2010-03-27 17:31:45

0

第二个例子可能等同于第一个在const前面有一个额外的extern。在第一种情况下,编译器可能组合了extern的两种用法。在第二种情况下,我会假设编译器不会出于任何原因而在外部范围外部出现任何东西。