【问题标题】:extern and extern "C" for variables用于变量的 extern 和 extern "C"
【发布时间】:2016-11-03 15:04:57
【问题描述】:

我正在编写一个 C++ 共享库供 C 程序使用。不过,我有一个关于externextern "C" 的问题。

考虑下面的代码

我的头文件是这样的:

#ifdef __cplusplus      
     extern "C" int global;
     extern "C" int addnumbers(int a, int b); 
 #else
      extern int global;
 #endif

这很好用;我只需要声明

int global;

在我的 .cpp 或我的 .c 文件中。但是,我不明白的是:

extern "C"extern 这里有什么区别?我尝试注释掉 extern "C" int global 并且它有效!为什么?

我知道extern "C" 用于进行C 链接。这就是为什么我有extern "C" int addnumbers(int,int)。换句话说,如果我想写一个用于 C 程序的 C++ 函数,我写extern "C"。现在,全局变量呢?我猜这里的情况有所不同?我希望 C 程序使用名为 global 的 C++ 变量,但我可以使用 extern 而不是 extern "C"。这是为什么?这对我来说并不直观。

评论:我不认为这是重复的,因为我问的是当你将它用于变量和函数时有什么区别。

【问题讨论】:

  • 我不认为这是重复的,因为我问的是当你将它用于变量和函数时有什么区别。
  • 我邀请您在您的问题中更清楚地说明这一点。
  • 虽然我很难发现 extern "C"extern 之间的区别和 extern "C"extern 用于变量。也许问题是 extern "C" 用于函数和变量时是否不同? 答案很简单“否”
  • 你不会看到变量的 extern "C" 和 extern 之间的区别,因为编译器对变量名不做任何事情。它只影响函数名。

标签: c++ c linkage extern-c


【解决方案1】:

通过将extern "C" 附加到您的 C++ 声明(对象和函数等)中,您可以为它们提供“C 链接” - 使它们可以从 C 代码中访问。如果您省略这个“语言链接”规范,编译器不会做任何努力来进行正确的链接。在函数的情况下,这会导致链接失败,因为重整。在全局变量的情况下,一切都可以正常工作,因为变量不需要修改。

但是,在我的系统 (MS Visual Studio) 上,如果我“忘记”在 C++ 头文件中指定 extern "C" 链接规范,C 和 C++ 之间的链接将不起作用。错误信息示例:

error LNK2001: unresolved external symbol "int global" (?_global)

虽然,当我使用 dumpbin 实用程序检查包含 global 定义的已编译 C++ 源代码时,我看到了

00B 00000014 SECT4  notype       External     | ?global@@3HA (int global)

因此 MS Visual Studio 会破坏全局变量的名称,除非它们具有 C 链接 - 这使得 C 链接规范成为强制性。


此外,请考虑以下示例:

namespace example {
    int global;
}

如果全局变量位于命名空间内,C 代码将无法访问它。在这种情况下,所有编译器都需要 C++ 声明中的正确链接规范:

namespace example {
    extern "C" int global;
}

结论:

当您需要 C 链接时,请使用 extern "C" - 它是函数还是全局变量都没有关系。如果它是一个全局变量,无论如何它都可以工作,但不能保证(并且可能很危险)。

【讨论】:

  • 关于修改全局和命名空间范围变量的好答案和见解!
  • 如果我有一个在 C++ 文件中声明的变量并且我希望它具有 C 链接怎么办?我不能将其设为“外部“C””,因为这样做会使它实际上是在本地定义的“外部”。它是一个全局变量,但在 C++ 文件中定义。
  • 简答:extern "C" 并不暗示extern。但是您绝对应该使用“”按钮来获得正确的答案。
【解决方案2】:

extern 只是告诉编译器下一个变量(全局)可能尚未声明,但它在不同的翻译单元中声明为全局,并且在链接阶段,符号“全局”将与内存中的一个区域。

虽然extern "C",正如一些人评论的那样,用于解决C++中的名称修改问题,但这个函数将被链接器称为addnumbers_i_i(或类似的东西),而在c中它的符号是addnumbers

【讨论】:

  • 其实extern是放在一个变量的声明中,表示它在别处定义以避免定义 b> 一个新变量(与另一个变量同名),它可能会导致链接器失败,这不是您想要共享单个全局变量时所需要的。
【解决方案3】:

"C++ 有一个特殊的关键字来声明一个带有 C 绑定的函数:extern "C"。声明为 extern "C" 的函数使用函数名作为符号名,就像 C 函数一样。因此,只有非-member 函数可以声明为 extern "C",并且它们不能被重载。"

C++ 中对于编译器生成的函数名没有标准。关键字 extern "C" 指示编译器生成 C 标准中的函数名。

【讨论】:

    【解决方案4】:

    我发现extern "C"是用来制作C标准编译的C++函数的,它与变量无关,因为C和C++中函数名的解决方案是不同的。如“void foo(int x, int y)”,C编译器将其翻译为“_foo”,而C++编译器将其翻译为“_foo_int_int”。

    【讨论】:

      猜你喜欢
      • 2019-12-22
      • 2012-06-22
      • 1970-01-01
      • 2021-01-26
      • 1970-01-01
      • 1970-01-01
      • 2015-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多