我有一个int ID
,我想在C ++中定义并提供C链接(为了简单起见,设计案例):
/* i.h */
#ifdef __cplusplus
extern "C" {
#endif
extern int ID;
#ifdef __cplusplus
}
#endif
这是使用int
:
/* m.cpp */
#include "i.h"
#include <iostream>
int main() { std::cout << ID << std::endl; }
/* m.c */
#include "i.h"
#include <stdio.h>
int main() { printf("%d\n", ID); }
现在我想知道的是extern "C"
和/或extern
的语法。以下是int ID
可以和不可以定义的方式:
/* i.cpp */
// const int ID = 88; // no C linkage, obviously, LNK2019/1120
// extern "C" const int ID = 88; // provides C linkage
// extern "C" { const int ID = 88; } // no C linkage, surprisingly, LNK2019/1120
// extern "C" { extern const int ID = 88; } // C linkage restored
编译:
cl /nologo /W4 m.cpp i.cpp /MD /EHsc
cl /nologo /W4 m.c i.cpp /MD
我不明白的是extern "C"
与{block}
一起使用时的语法。我必须重复extern
,而使用extern "C"
的无块形式我不会。这只是一个语法怪癖还是还有更多呢?
我在Dale Rogerson的 Inside COM 第98页偶然发现了这个问题。有一个嵌套extern
的代码清单和一条旨在澄清的评论(但我不明白):
#include <objbase.h>
extern "C"{
extern const IID IID_IX = {0x32bb8320, 0x41b, 0x11cf, ...};
// The extern is required to allocate memory for C++ constants.
}
任何人都可以解释内部extern
吗?
答案 0 :(得分:3)
内部extern
表示预期:&#34;符号在其他地方定义,它具有外部链接,不在此单元中为其分配空间(除非在此定义)&#34;。
外部extern "C" { ... }
可能有一点误导性的语法,它只告诉编译器&#34;如果你在这个块里面用外部链接创建任何符号的名称,请使用传统的C命名( C语言链接)而不是C ++名称修改( C ++语言链接)为他们&#34;。但它没有指明块内的所有内容都是在其他地方定义的#34; (具有外部链接) - 它们仍然使用默认的内部链接进行声明。这就是你需要内部extern
的原因。
单行变体extern "C" <variable declaration>
只是一个简写,因为如果你关心它的跨单位符号名称,你可能想要定义一个外部变量。
(作为旁注,我还会在i.h
中加入i.cpp
,这样我就不用再记得在实施中再混淆extern "C"
了。)
答案 1 :(得分:2)
问题在于const
和extern
互相交战。 const
表示(除其他外),&#34;将此定义设为内部定义,除非其上有明确的extern
。&#34;。当定义位于extern "C"
块中时,定义上没有extern
直接,因此&#34;隐含内部&#34;来自const
优先。其他定义都直接在定义上有extern
,因此它变为外部。
答案 2 :(得分:1)
以下是int ID的定义方式:
小心! extern "C"
在不同的环境中有不同的效果。
N3797§7.5/ 7:
直接包含在 linkage-specification 中的声明被处理 就好像它包含
extern
说明符(7.1.1)一样 确定声明的名称与是否为a的链接 定义即可。此类声明不应指定存储类别。extern "C" int i; // declaration extern "C" { int i; // definition }
因此,您的代码段中的第二行只是一个声明,而您的第三行也是一个定义。这会改变 linkage-specification 对声明的影响 - 您不能在C ++转换单元C链接中指定名称。你必须把它作为一个纯粹的宣言。