;
1. 将上述代码保存到.c文件中
若上述代码用c编译器编译,由于c语言中无函数重载,所以,在程序运行时出错。
出错原因:因为在c语言中,c编译器只是在函数名的前面加下划线进行简单的重命名;
为了验证结果,将上述的代码稍作修改( float Add(float a, float b) -> float Add1(float a, float b) )。然后用 vs Debug模式编译.c文件,之后在.map文件中就可以看到结果。
在vs中,map文件生成的步骤设置:工程名右击—>属性—->配置属性—->链接器—–>调试—->生成映射文件—>选择是;
2. 将上述代码保存到.cpp文件中
若上述代码用c++编译器编译,由于c++语言支持函数重载,所以程序正常运行;但是,在不同c++编译器之间对函数重载的机制也是不一样,接下来分别用vs 和 g++介绍。
(1)用 vs Debug模式编译.cpp文件,之后就可以在map文件中看到如下结果,
// ‘?’表示名称开始,‘?’后边是函数名;“@@YA”表示参数表开始,后边的3个字符分别表示返回值类型,两个参数类型;“@Z”表示名称结束。
(2)在Ubuntu下测试(需要安装g++编译器),执行以下指令:
1)g++ test.cpp
2)objdump a.out -t > test.out // -t是表示生成符号表,最后是将生成的符号表用重定向符号放在test.out文件。
3)vi test.out
打开test.out文件,就会发现,整形数相加的函数Add(int a,int b)
生成的符号表中,Add函数名被记录为_Z3Addii。
其中,_Z表示符号表名称开始, 3代表函数名的字符个数,ii代表参数列表顺序中2个形参的类型;
综述,无论使用何种编译器,在.cpp文件中,虽然两个函数的函数名一样,但是他们在符号表中生成的名称不一样,所以是可以编译通过的。
由上述分析可知,c编译器 与 c++编译器 对函数的重命名规则不一样;那么,在c++中如何确保将一段c代码以c编译器的方式被编译呢?---- 使用 extern 关键字
1 // 使用方式1
2 extern "C"
4 // C-Style Compilation
7 // 使用方式2
8 //__cplusplus 是 c++ 编译器内置的标准宏定义
9 //__cplusplus 的意义:确保C代码以统一的C方式被编译成目标文件
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
15 // C-Style Compilation
17 #ifdef __cplusplus
18 }
19 #endif
extern "C" 的使用方式