GCC内部符号装饰有什么问题

what is wrong with the gcc internal symbol decoration?

本文关键字:什么 问题 内部 符号 GCC      更新时间:2023-10-16
#include <stdio.h>
namespace myname{
    double var = 42;
}
extern "C" double _ZN6myname3varE = 10.0;
int main(){
    printf("%dn", _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( 保留给实现以供任何使用。

为什么要重新定义_ZN6myname3varE

C++变量myname::var由 GCC 重命名为_ZN6myname3varE。 您还定义了一个名为 _ZN6myname3varE 的 C(即非残缺(变量。 因此,您对同一交易品种有多个定义。


警告[...]是什么意思?

标准用法是:

福.H

extern "C" int myvariable;

foo.c/cc

#include "foo.h"
int myvariable = 42;

我不确定C++标准是否允许初始化extern "C"变量(即像您正在做的那样(。 但是编译器肯定会警告你,你正在做的事情可能没有意义。

第一条警告消息意味着如果在变量的声明中包含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在评论中指出的那样(,您可以在行中包含大括号以允许初始值设定项:

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("%fn", myname::var);

第三条消息,错误,来自汇编程序。 因为第一条消息只是一个警告,所以您实际上有两个不同的定义,当它们被破坏时,会转换为 _ZN6myname3varE ,具有两个不同的初始值设定项。 您只允许使用一个定义 — 一个定义规则。

但是,以下划线后跟大写字母开头的名称是为实现保留的,因此尝试直接使用该名称_ZN6myname3varE,您将调用未定义的行为。 不要乱搞未定义的行为;避免它。