SylixOS下移植C++程序——命名粉碎

2023-11-08

1. 概念

1.1 命名粉碎

命名粉碎(name mangling),又称命名修饰。name mangling是一种在编译器和链接器之间用于通信的符号协议,其目的在于按照程序中的语言规范,使符号具备足够的语义信息以保证链接过程准确无误的进行。

编译器将目标源文件中的名字进行调整,由于C++中支持overloadoverride,所以C++的编译器必须有name mangling把函数名和变量名进行调整。

1.2 方法重载

方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或者参数的个数。调用重载方法时,编译器会通过检查调用方法的参数类型以及个数选择一个恰当的方法。C++中支持方法重载,示例代码如程序清单1-1所示。

程序清单 1-1 方法重载示例

#include <iostream>
#include <iomanip>
using namespace   std;
void Swap (int *a, int *b)                                 /* 交换 int 变量的值        */
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
void Swap (float *a, float *b)                            /* 交换 float 变量的值       */
{
    float temp = *a;
    *a = *b;
    *b = temp;
}
void Swap (char *a, char *b)                              /* 交换 char 变量的值        */
{
    char temp = *a;
    *a = *b;
    *b = temp;
}
int main (int agrc, char **argv)
{
    int n1 = 100, n2 = 200;
    Swap(&n1, &n2);                                       /* 交换 int 变量的值        */
    cout<<n1<<", "<<n2<<endl;
 
    float f1 = 12.5, f2 = 56.93;
    Swap(&f1, &f2);                                       /* 交换 float 变量的值       */
    cout<<f1<<", "<<f2<<endl;

    char c1 = 'A', c2 = 'B';
    Swap(&c1, &c2);                                       /* 交换 char 变量的值        */
    cout<<c1<<", "<<c2<<endl;
   
    return 0;
}

运行程序清单1-1中代码,执行结果如图1-1所示。

图 1-1 方法重载运行结果

注意:函数的返回值不能作为重载的依据,函数重载的规则:

1. 函数名字必须相同;

2. 参数列表不同(个数不同,类型不同,顺序不同);

3. 函数的返回值不能构成函数的重载。

2. 命名粉碎规则

2.1 gcc 和 g++ 编译器的命名粉碎

不同的编译器进行不同的方式进行name mangling ,下面介绍gcc和g++的name mangling 的规则,示例代码如程序清单2-1所示。

程序清单 2-1 示例代码

#include <stdio.h>

int fun_test_sylixos ( void )
{
	return (0);
}
int fun_test_linux ( void )
{
	return (0);
}

int main (int argc, char **argv)
{
      fun_test_sylixos();
fun_test_linux();

	 return (0);
}

使用gcc编译器,生成目标文件,通过nm命令查看目标文件中的符号表。操作如图2-1所示。

图 2-1 gcc 编译

使用g++编译器,生成目标文件,通过nm命令查看目标文件中的符号表。操作如图2-2所示。

图 2-2 g++编译

由上述结果可知,gcc编译器编译后对应的符号表中几乎没有对函数进行修饰,而g++对函数的改编比较复杂。所以,如果一个由C语言编译的目标文件中调用了C++中实现的函数,肯定会出错的,因为符号不匹配。

这个时候可以使用C++的关键字“extern C”。对应的代码如程序清单2-2所示。

程序清单2-2 示例代码

#include <stdio.h>
#ifdef __cplusplus
Extern “C” {
#endif
int fun_test_sylixos ( void )
{
	return (0);
}
int fun_test_linux ( void )
{
	return (0);
}
#ifdef __cpluscplus
}
#endif
int main (int argc, char **argv)
{
      fun_test_sylixos();
fun_test_linux();

	 return (0);
}

使用gcc编译器结果如图2-3所示。

图 2-3 gcc编译

使用g++编译器结果如图2-4所示。

图 2-4 g++ 编译

可见,使用关键字后,符号就按照C语言的格式来组织了。

2.2 命name mangling名规则

        GNUC++name mangling方案和其他C++编译器方案不同,所以一种编译器生成的目标文件并不能被另外一种编译器生成的目标文件使用。

简单对_Z16fun_test_sylixosv做个介绍:

1. C++语言中规定:以下划线并紧挨着大写字母开头或者以两个下划线开头的标识符都是C++语言中保留的标示符。所以_Z16fun_test_sylixosv是保留的标识符,g++编译的目标文件中的符号使用_Z开头(C99标准)。

2. 接下来的16表示接下来的要表示的一个字符串对象的长度(所以函数命名的时候不能用数字开头),所以fun_test_sylixos16个字符就作为函数的名称被识别出来了。

3. 接下来的每个小写字母表示参数的类型,v表示void类型。

下面介绍C++中命名的修饰规则,以下为内置的编码类型:

  <builtin-type>    ::= v  # void 
                 ::= w  # wchar_t 
                 ::= b  # bool 
                 ::= c  # char 
                 ::= a  # signed char 
                 ::= h  # unsigned char 
                 ::= s  # short 
                 ::= t  # unsigned short 
                 ::= i  # int 
                 ::= j  # unsigned int 
                 ::= l  # long 
                 ::= m  # unsigned long 
                 ::= x  # long long, __int64 
                 ::= y  # unsigned long long, __int64 
                 ::= n  # __int128 
                 ::= o  # unsigned __int128 
                 ::= f  # float 
                 ::= d  # double 
                 ::= e  # long double, __float80 
                 ::= g  # __float128 
                 ::= z  # ellipsis 
                 ::= u <source-name>    # vendor extended type

一些其他的修饰规则请参照博客资料或者其他的参考资料。

3. 工具使用

3.1 nm

nm是编译器中的名字工具,列出目标文件中的符号表,下面介绍几种常用的用法:

nm – C:表示name mangling

nm –U:显示没有定义的符号

示例用法如图3-1所示。

图3-1 nm 查看符号表

nm的一些其他的用法请参照网上资料。

3.2 C++filt

c++filt 工具查看一个经过命名修饰后的符号,输出修饰之前的符号。示例用法如图3-2所示。

图3-4 c++filt工具

3.3__cxa_demangle()

          __cxa_demangle()函数用于将mangled_name所指向的mangled进行demangle并将结果存放在buf中,n为buf的大小。
  status存放函数执行的结果,返回值为0表示执行成功。
下面是使用这个接口函数进行demangle的例子:

#include<iostream> 
#include<cxxabi.h> 

using namespace std; 
using namespace abi; 
 
int main(int argc,char *argv[]) 
 { 
        const char * mangled_string = "_Z16fun_test_sylixosv "; 
 
        char   buffer[100]; 
        int     status; 
        size_t   n = 100; 

        __cxa_demangle(mangled_string,buffer,&n,&status); 
 
        cout<<buffer<<endl; 
        cout<<status<<endl; 

        return 0; 
} 

执行结果如图3-5所示。

图 3-5  __cxa_demangle运行示例














本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SylixOS下移植C++程序——命名粉碎 的相关文章

随机推荐

  • python 引用(import)文件夹下的py文件的方法

    Python包含子目录中的模块方法比较简单 关键是能够在sys path里面找到通向模块文件的路径 下面将具体介绍几种常用情况 1 主程序与模块程序在同一目录下 如下面程序结构 src mod1 py test1 py 若在程序test1
  • 【死磕 Redis】----- Redis 数据结构: skiplist

    原文 https www cmsblogs com category 1391389927996002304 chenssy 关于跳跃表其实在 JUC 里面有一个并发容器就是利用跳跃表来实现的 ConcurrentSkipListMap 死
  • python开发_常用的python模块及安装方法

    adodb 我们领导推荐的数据库连接组件 bsddb3 BerkeleyDB的连接组件 Cheetah 1 0 我比较喜欢这个版本的cheetah cherrypy 一个WEB framework ctypes 用来调用动态链接库 DBUt
  • SpringBoot2.0(Spring读取配置文件常用方法,打war包在Tomcat中启动)

    目录 一 SpringBoot中读取配置文件的常用方法 1 1 使用 Value读取 1 2 使用 ConfigurationProperties 1 3 使用Environment 1 4 自定义配置文件读取 二 SpringBoot部署
  • 直接修改html文本页面没变化,DOM问题:点击按钮的时候,修改input元素的value属性值,为什么在HTML结构上没有变化?...

    代码 无标题文档 span background lime window nl ad function 获取input span var oTxt document getElementsByTagName input 0 var oBtn
  • 什么是元宇宙:我们在哪里,我们要去哪里

    自Facebook于 2021 年 10 月 28 日更名为 Meta 以来 启发新名称的模糊概念一直是讨论的热门话题 虽然元宇宙似乎是 Meta 野心的产物 但事实并非如此 一些人会争辩说 马克扎克伯格在Connect 2021会议主题演
  • 基于 FFmpeg 的跨平台视频播放器简明教程(六):使用 SDL 播放音频和视频

    系列文章目录 基于 FFmpeg 的跨平台视频播放器简明教程 一 FFMPEG Conan 环境集成 基于 FFmpeg 的跨平台视频播放器简明教程 二 基础知识和解封装 demux 基于 FFmpeg 的跨平台视频播放器简明教程 三 视频
  • qt透明度设置

    QPaintEvent QPainter painter this painter setRenderHint QPainter Antialiasing painter setBrush m color painter setPen Qt
  • MySQL的优化

    目录 一 概念 二 查看SQL执行频率 三 定位低效率执行SQL 定位低效率执行SQL 慢查询日志 操作 定位低效率执行SQL show processlist 四 explain分析执行计划 字段说明 explain中的id explai
  • STM32+LittleVgl(LVGL)文件系统使用

    目录 一 硬件及软件准备 二 前言 三 显示效果 四 移植文件到工程目录下 五 将文件添加进工程中 六 使能文件 七 修改 lv port fs c 文件 八 修改main c 九 将图片资源拷贝到外部存储器中 一 硬件及软件准备 完整工程
  • 【迪文屏】踩坑指南——汉字显示乱码、背景图不显示问题的解决方法

    迪文屏支持的字库文件有HZK DZK Bin格式 迪文屏文字乱码请按下图中步骤一个个排查 迪文屏更改背景显示不出来可能是未生成icl文件或者icl文件位置未设置对 所以系统找不到 生成的icl图标库文件后 记得在CFG配置文件更改ILC位置
  • 数据库之DML的基本操作

    DML 数据操作语言 对表记录的操作 增 删 改 1 插入数据 insert into 表名 列名1 列名2 values 列值1 列值2 在表名后给出要插入的列名 其他没有指定的列插入NILL 在values后给出列值 值的顺序和个数必须
  • HTTPS工作原理原理及常见状态码

    HTTPS工作原理原理 简介 HTTPS是常用的web协议 用来交互网页数据 由于HTTP是不加密的 在公网上明文传输 缺少保密性 所以出现了安全加密的HTTP协议 HTTPS协议 HTTPS协议是在SSL协议基础上的HTTP协议 SSL协
  • JVM系列(八) JVM 垃圾收集算法

    前面我们了解了很多JVM配置垃圾回收的方式 但是具体垃圾是如何被回收的 或者说垃圾回收算法有哪些 今天我们文章主要讲解一下垃圾回收算法 1 分代收集理论 我们都知道 很早的JVM会把堆分为几个区域 新生代 老年代 永久代等区域 为什么要这么
  • JSP详细讲解

    JSP详细讲解 前言 一 JSP 介绍 二 JSP 运行原理 1 JSP 技术特点 2 JSP 与 Servlet 区别 三 JSP 的使用 1 JSP 的三种原始标签 2 JSP 原始标签的使用 3 JSP 的指令标签 4 JSP 指令标
  • 王爽汇编语言课程设计1

    一 实验要求 在屏幕输出实验七中的数据 二 设计思路 1 将实验七的程序编写成一个子过程finishing 在主程序中调用 可以获得实验七种指定格式的table段数据 设置es bx指向table段中第一行 2 创建一个数据缓存区buffe
  • 双电源切换电路的几种方案

    一 使用两个二极管 VBUS和VBAT单独供电的情况很好理解 由于二极管的单向性 不会发生电流的倒灌 当VBUS和VBAT都有电时 VBUS为5V VBAT为3 7V 此时D17处于反向截至状态 只有VBUS输出但VOUT 优点是方案简单
  • nuxt项目中引用less/scss全局变量

    nuxt项目中有些样式需要经常使用 并且未来有可能会改 比如主题色 theme color 所以希望在一个地方定义后 后面直接引用变量即可 但是正常使用时 less的变量是不能跨文件使用的 下面使用 nuxtjs style resourc
  • 国外IP地址汇总

    ip route 1 0 0 0 255 255 255 0 10 201 130 13 ip route 1 1 1 0 255 255 255 0 10 201 130 13 ip route 1 2 3 0 255 255 255 0
  • SylixOS下移植C++程序——命名粉碎

    1 概念 1 1 命名粉碎 命名粉碎 name mangling 又称命名修饰 name mangling是一种在编译器和链接器之间用于通信的符号协议 其目的在于按照程序中的语言规范 使符号具备足够的语义信息以保证链接过程准确无误的进行 编