C++编译之(1)-g++单/多文件/库的编译及C标准的发展历程

g++编译入门

本文为您介绍g++的编译用法;通过从最简单的单文件编译,到多文件编译,再到动态库、静态库的编译及使用;
例子都经过实际编译并运行,可谓全网最良心之作呐,放心拷贝粘贴学习!

1、g++的编译单文件

c++的程序编译的过程如下:

1.预编译->2.编译->3.汇编->4.链接

以个Test.cpp为例说明整个编译过程

Test.cpp 文件如下

#include <iostream>
#define MAX_NUM 10
// 定义宏
int main() {
   
    // 输出Hello world
    std::cout<<"Hello world!"<<std::endl;
    // 输出Max+n
    int n = 100;
    std::cout<<"MAX_NUM+n:"<<MAX_NUM+n<<std::endl;
    return 0;
}
1)预编译

宏的替换,还有注释的消除,还有找到相关的库文件

g++ -E Test.cpp > Test.i

只做预处理,生成一个Test.i的文件,该文件多了很多内容,我们省略前面1万+行,只看最下面对我们的写的源码做了什么处理;
Test.i内容如下

int main() {
   

    std::cout<<"Hello world!"<<std::endl;

    int n = 100;
    std::cout<<"MAX_NUM+n:"<<10 +n<<std::endl;
    return 0;
}

这就是预处理做的我们能理解的事,其他的有空自己再慢慢深挖。

2)编译

将预处理后的文件转换为汇编文件,里面为汇编指令

g++ -S Test.i

当然也可以直接将源代码cpp处理 g++ -S Test.cpp,两者编译后的输出结果一模一样

编译后,将得到一个Test.s的文件,前面0行开始截取部分内容如下:

	.file	"Test.cpp"
	.text
	.section	.rodata
	.type	_ZStL19piecewise_construct, @object
	.size	_ZStL19piecewise_construct, 1
_ZStL19piecewise_construct:
	.zero	1
	.local	_ZStL8__ioinit
	.comm	_ZStL8__ioinit,1,1
.LC0:
	.string	"Hello world!"
.LC1:
	.string	"MAX_NUM+n:"
	.text
	.globl	main
	.type	main, @function
main:
.LFB1522:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	leaq	.LC0(%rip), %rsi
	leaq	_ZSt4cout(%rip), %rdi
	call	_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@PLT
	movq	%rax, %rdx
	movq	_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GOTPCREL(%rip), %rax
	movq	%rax, %rsi
	movq	%rdx, %rdi
	call	_ZNSolsEPFRSoS_E@PLT
	movl	$100, -4(%rbp)
	leaq	.LC1(%rip), %rsi
	leaq	_ZSt4cout(%rip), %rdi
	call	_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@PLT
	movq	%rax, %rdx
	movl	-4(%rbp), %eax
	addl	$10, %eax
	movl	%eax, %esi
	movq	%rdx, %rdi
	call	_ZNSolsEi@PLT
	movq	%rax, %rdx
	movq	_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GOTPCREL(%rip), %rax
	movq	%rax, %rsi
	movq	%rdx, %rdi
	call	_ZNSolsEPFRSoS_E@PLT
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
...

显然,上面的是机器无关的汇编指令

3)汇编

将汇编文件转为目标文件

g++ -c Test.s # 当然也可以直接使用`g++ -c Test.cpp`从源文件直接输出

汇编执行后,将生成Test.o的目标文件(二进制文件)

4)链接

将目标文件和库文件整合为一个可执行文件

g++ Test.o -L usr/include/iostream

-L后为库文件目录

命令执行后,将生成一个a.out,我们可以运行一下该文件,前面的代码正常运行,如下所示:

$ ./a.out 
Hello world!
MAX_NUM+n:110

使用-o可以为可执行文件命名

g++ Test.o -o Test -L usr/include/iostream
# 同理可以直接对源码输出`g++ Test.cpp -o Test -L usr/include/iosream`

执行后,将输出Test的可执行文件

5)一步到位编译
# 直接编译
g++  Test.cpp -o Test
# 执行结果
./Test
Hello world!
MAX_NUM+n:110

直接输出Test可执行文件

g++常用的参数

-c 生成.o目标文件

-o可执行文件命名

-shared 指定生成动态链接库

-static 指定生成静态链接库

-L 要链接的库所在目录

-l 指定链接时需要的库,隐含命名规则,即自动在前加lib,在后加.a或.so确定库文件名

-std 设置C语言版本 g++ -std=c11 Test.cpp -o Test

2、g++编译多文件

前面我们知道如何编译一个c++代码,如果多个c++文件组织在一起如何用g++编译呢?

我们基于前面测试项目,再创建一个文件HelloToolsClass.cpp,现在我们有两个文件了:Test.cppHelloToolsClass.cpp

其中HelloToolsClass.cpp为完整的类声明及定义为一体文件,内如如下;

class HelloTools{
   
    public:
    void print(int a, int b)<
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值