3

我正在尝试使用 externs 在 C++ 中与 Ada 交互。这两种实现有什么区别?

实施 A

namespace Ada
{
    extern "C"
    {
        int getNumber();
        int index;
        int value;
    }
}

实施 B

namespace Ada
{
    extern "C"
    {
        int getNumber();
    }
    extern "C" int index;
    extern "C" int value;
}

两种实现都编译得很好。但是 Impl-A 无法链接,我得到indexvalue的多重定义错误。我只是想了解这些差异。

4

3 回答 3

7

extern "C" 仅传达用于 extern "C" 块内代码的链接约定。该块中的任何内容都将被链接起来,就好像它是纯 c 一样。令人困惑的是, extern int 完全不同。这意味着您承诺在某处有一个实际的 int 命名索引和一个实际的 int 命名值,但在这里找不到它们。在您的实现-A 中,int 实际上不是第二种意义上的 extern - extern "C" 仅表示它们提供了严格的 c 链接约定。

相同的关键字但完全不同的用途,这是不幸的,因为它会导致这样的奇怪问题。混合它们是合法的(显然),但它们的行为方式并不像它们的名字所暗示的那样。

编辑

有关 C++ 标准中定义的外部怪异的真实定义,请参阅 Charle 的回复。

于 2010-09-03T20:04:07.017 回答
7

应用于大括号括起来的声明序列的链接说明符(即extern "C"extern "C++")对封闭的声明是否为定义没有影响,但是应用于单个声明的链接说明符被视为extern说明符,以确定是否声明也是定义。(C++03 的 7.5 第 7 段)

所以:

extern "C" { int a; } // a is declared and defined

extern "C" int a; // a is just a declaration (as if extern int a;)

extern "C" int a = 0; // a is a definition because of the initializer.
于 2010-09-03T20:17:28.990 回答
3

我不确定为什么第二个有效,但你想要

namespace Ada
{
    extern "C"
    {
        int getNumber();
        extern int index;
        extern int value;
    }
}

因为您只想声明 indexand value,而不是定义它们。(有关差异,请参见此答案。)

于 2010-09-03T19:49:55.360 回答