5

以下两个声明有什么区别?我认为它们是等效的,但是第一个示例有效,而第二个示例无效。我的意思是它可以编译并运行,但位图显示代码显示为空白。我还没有完成它,但我错过了一些明显的东西吗?GUI_BITMAP 是描述位图的简单结构。这适用于 VC++ 2005,但我认为它在 VC++ 2008 中也失败了。在这个问题上抓挠我的头......

样品 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++ 有一些我不明白的微妙之处。如果外部区域中的东西是函数,那么两个样本将是相同的,对吧?

4

2 回答 2

3

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

ARM 文档的这一页很好地描述了这个问题 - 我希望在您的情况下会发生类似的行为:

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

编辑:更多搜索发现此问题是由于违反“单一定义规则”而引起的,因此编译器/链接器不需要通知您该问题。这使您的问题与此问题重复。

于 2010-03-27T03:57:31.627 回答
0

第二个示例可能等同于第一个示例,在 const 前面有一个额外的 extern。在第一种情况下,编译器可能结合了 extern 的两种用法。在第二种情况下,我会假设编译器不会出于任何原因排除 extern 范围 extern 中的所有内容。

于 2010-03-27T03:57:06.060 回答