#include <stdio.h>
namespace myname{
double var = 42;
}
extern "C" double _ZN6myname3varE = 10.0;
int main(){
printf("%d\n", _ZN6myname3varE);
return 0;
}
gcc
编译结果为:
Jim@ubuntu:~/workspace/vi_edit$ g++ testSymble.cpp -o testSymble
testSymble.cpp:7:19: warning: ‘_ZN6myname3varE’ initialized and declared ‘extern’ [enabled by default]
testSymble.cpp: In function ‘int main()’:
testSymble.cpp:10:32: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘double’ [-Wformat]
/tmp/cczIjRfH.s: Assembler messages:
/tmp/cczIjRfH.s:14: Error: symbol `_ZN6myname3varE' is already defined
为什么重新定义_ZN6myname3varE
?
警告‘_ZN6myname3varE’ initialized and declared ‘extern’ [enabled by default]
意味着什么?
如果程序在保留它的上下文中声明或定义名称,除了该子句明确允许的名称外,该行为是未定义的。
17.4.3.1.2全球名称
每个名称包含双下划线(_ _)或以下划线开头,后跟大写
信(2.11)保留给任何用途的实施。
答案 0 :(得分:3)
为什么重新定义
_ZN6myname3varE
?
GCC的C ++变量myname::var
为name-mangled到_ZN6myname3varE
。您还定义了一个名为_ZN6myname3varE
的C(即非变形)变量。因此,您有相同符号的多个定义。
警告 [...] 是什么意思?
标准用法是:
<强> foo.h中强>
extern "C" int myvariable;
<强>的foo.c /立方厘米强>
#include "foo.h"
int myvariable = 42;
我不确定C ++标准是否允许extern "C"
变量的初始化(就像你正在做的那样)。但编译器当然会警告你,你正在做的事情可能没有意义。
答案 1 :(得分:0)
第一条警告消息表示如果在变量声明中包含extern
,则不能包含初始值设定项。因此,这两行都会产生警告:
extern "C" int i = 9;
extern int j = 10;
你可以写:
int i = 9;
int j = 10;
或:
extern "C" int i;
extern int j;
或(Adam Rosenfield中指出comment),您可以在行中包含大括号以允许初始值设定项:
extern "C" { int i = 9; }
应用于您的代码,您无法将初始化程序= 42
放在extern "C"
行中,或者您需要编写:
extern "C" { double _ZN6myname3varE = 10.0; }
孤立地,无视最后的问题,应该“有效”。
第二个警告表示namespace myname { double var = 42; }
是double
,因此%d
转换规范是错误的;它应为%f
或%e
或%g
或此主题的变体。
printf("%f\n", myname::var);
第三条消息,即错误,来自汇编程序。因为第一条消息只是一个警告,所以实际上有两个不同的定义,当被修改时,使用两个不同的初始值设定项转换为_ZN6myname3varE
。您只能使用一个定义 - 一个定义规则。
但是,以下划线后跟大写字母开头的名称是为实现保留的,因此通过尝试直接使用名称_ZN6myname3varE
,您将调用未定义的行为。不要乱用未定义的行为;避免它。