gcc 和 g++
在已编译好的 C 或者 C++ 代码的前提下,GCC 编译器已提供了调用接口,可以通过执行 gcc 或者 g++ 指令来调用 GCC 编译器,两者都可以编译 C 或者 C++ 语言程序,但这不是两者的区别。
实际上只要是 GCC 支持编译的程序代码,都可以使用 gcc 命令完成编译,可以说 gcc 是 GCC 编译器的通用编译指令,因为 gcc 指令根据程序文件的后缀名可以执行判断出当前程序所用编程语言的类别:
-
xxx.c:默认以编译 C 语言程序的方式编译此文件;
-
xxx.cpp:默认以编译 C++ 语言程序的方式编译此文件;
-
xxx.m:默认以编译 Objective-C 语言程序的方式编译此文件;
-
xxx.go:默认以编译 Go 语言程序的方式编译此文件;
-
gcc 指令对 .c 文件则以 C 语言代码对待,对 .cpp 文件则以 C++ 代码对待;
-
g++ 指令对.c 或者 .cpp 文件则都以 C++ 代码对待;
-
gcc 指令编译执行 C++ 程序,需要添加命令使得链接必要的 C++ 标准库:
[root@bogon ~]# gcc -xc++ demo.cpp -lstdc++ -shared-libgcc
- 使用g++编译文件时,g++会自动链接标准库STL,而gcc不会自动链接STL。
命名倾轧(函数重载及原理)
函数重载
C 语言中一个函数不能与另一个函数重名;C++ 中只要函数的参数列表与另一函数的参数列表不完全相同,函数名就可以相同。
重载原则
- 函数名相同,函数参数列表不同(类型、个数、顺序);
- 匹配原则1:严格匹配,找到再调用;
- 匹配原则2:通过隐式类型转换寻求一个匹配,找到再调用;
- 返回值类型不构成重载条件。
重载实现原理
利用 name mangling(倾轧)技术对函数名进行更改,区分参数不同的同名函数。
查看符号表
- nm 目标文件;
- objdump -t 目标文件;
- readelf -s 目标文件
- strings 目标文件
GCC 自动识别的文件扩展名
文件名 + 扩展名 |
GCC 编译器识别的类型 |
file.c |
尚未经过预处理的C 源程序文件 |
file.j |
经过预处理操作,但未进行编译、汇编和连接的 C 源代码文件 |
file.cpp file.cp file.cc file.cxx file.CPP file.c++ file.C |
尚未经过预处理操作的 C++ 源代码文件 |
file.ii |
经过预处理操作,但未进行编译、汇编和连接的 C++ 源代码文件 |
file.s |
经过编译生成的汇编代码文件 |
file.h |
C、C++或者 Objective-C++ 语言头文件 |
file.h hfile.H file.hp file.hxx file.hpp file.HPP file.h++ file.tcc |
C++ 头文件 |
命名反倾轧
c++filt _Z4funci
查看反倾轧的符号表
nm -C 目标文件
objdump -t -C 目标文件
禁用命名倾轧
C++ 命名倾轧的函数无法被 C 调用。C++ 函数必须是没有倾轧的才能调用。
使用声明 extern "C"
禁止命名倾轧:
#ifndef __CPP_H_
#define __CPP_H_
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
int fun(int n);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // __CPP_H_
编译
函数声明 |
编译器 |
编译函数符号 |
查找函数符号 |
void func(int) |
g++ |
_Z4funci |
_Z4funci |
void func(int) |
gcc |
func |
func |
extern "C" void func(int) |
g++ |
func |
func |
extern "C" void func(int) |
gcc |
错误 |
|