gcc内部符号装饰有什么问题?

时间:2013-07-17 04:39:51

标签: c++ gcc compiler-warnings

#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)保留给任何用途的实施。

2 个答案:

答案 0 :(得分:3)

  

为什么重新定义_ZN6myname3varE

GCC的C ++变量myname::varname-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,您将调用未定义的行为。不要乱用未定义的行为;避免它。