2

我读了 Dale Rogerson 的书“Inside COM”。在第 5 章中,他写道(对不起,我翻译成英文):

extern "C"用于 C 链接。如果函数被标记为extern "C",编译器不会将函数的名称更改为其他名称,例如: ?CreateInstance@@YAPAUIUncnown@@XZ.

这对我来说很清楚。但作者extern "C"在其他地方进一步使用,并没有解释它的原因:

#include <objbase.h>

extern "C" 
{
    // {32bb8320-b41b-11cf-a6bb-0080c7b2d682}
    extern const IID IID_IX = 
        {0x32bb8320, 0xb41b, 0x11cf,
        {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

    // {32bb8321-b41b-11cf-a6bb-0080c7b2d682}
    extern const IID IID_IY = 
        {0x32bb8321, 0xb41b, 0x11cf,
        {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

    // {32bb8322-b41b-11cf-a6bb-0080c7b2d682}
    extern const IID IID_IZ = 
        {0x32bb8322, 0xb41b, 0x11cf,
        {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

    // The extern is required to allocate memory for C++ constants.
}

它不是一个函数......为什么作者extern "C"在这种情况下使用?

最好的问候,安德烈

4

2 回答 2

4

像这样的块上的 extern "C" 就像将 extern "C" 应用于块中的每个声明;它声明所有这些都使用 C 链接。

非函数上的 extern "C" 与函数上的 extern "C" 做同样的事情;它使对象使用 C 语义进行命名,以及其他任何相关的内容。

有关详细信息,您可能需要参考标准,第 7.5 节链接规范 [dcl.link](尽管它是使用难懂的英语形式编写的)。


语言链接是为了使从不同语言访问声明的实体成为可能。这究竟意味着什么取决于特定的语言和 C++ 实现。传统上,对于 C,这意味着函数的符号和调用约定发生了变化。据我所知,在大多数实现中,非函数没有什么不同。只是语言规范并没有说你可以期望从 C 访问这些实体来工作,除非你使用 extern "C"。

于 2012-11-01T18:12:17.773 回答
0

对于您的问题,可能只是一个愚蠢的解决方法。我发现,在 cpp 文件中使用 c 函数时,理论上需要 extern。但是我发现在eclipse的氧气版本中,我们不必指定extern c,我们也可以在cpp文件中直接使用c函数和printf语句,就可以了。没有尝试过旧版本的eclipse。

我的解决方案可能不是很有帮助,但您可以尝试一下。它对我有用。

据我记得标准,默认情况下,所有函数声明都被视为“外部”,因此无需显式指定。这不会使这个关键字无用,因为它也可以与变量一起使用(在这种情况下 - 它是解决链接问题的唯一解决方案)。但是有了这些功能 - 是的,它是可选的。

更冗长的答案是它允许您使用在另一个源代码文件中编译的变量,但不为变量保留内存。因此,要使用 extern,您必须有一个源代码文件或一个库单元,其中包含顶层变量(而不是函数内)的内存空间。现在,您可以通过在其他源代码文件中定义同名的外部变量来引用该变量。

一般来说,应该避免使用外部定义。它们很容易导致难以管理的代码和难以定位的错误。当然,也有其他解决方案不切实际的例子,但它们很少见。例如,stdin 和 stdout 是映射到 stdin.h 中 FILE* 类型的外部数组变量的宏;该数组的内存空间位于标准 C 库单元中。

于 2017-05-15T12:36:59.270 回答