GCC的学习(一)GCC简介及其常用选项

一、什么是GCC?

GCC(the GNU Compiler Collection)GCC是GNU编译器集合,它包括了C/C++、Objective-C、Fortran、Ada和Go语言的前端和对应的库(libstdc++)GCC初衷是为完全免费的GNU系统编写的编译器。

二、程序编写到执行过程是怎么样的?

一个C程序从编辑到执行需要经过以下过程:

预处理
汇编
编译
链接
载入内存并链接依赖库
编写源代码_*.c/*.cpp
已预处理文件_*.i
汇编文件_*.s
目标文件_*.o
可执行或者库文件_*.exe/*.so/*.a
程序被CPU执行

三、编译过程中文件内容的变化

编译一共需要处理四个文件(CISO):

  • 源代码文件(*.c)
  • 预处理文件(*.i)
  • 汇编文件(*.s)
  • 目标文件(*.o)

最后一步处理目标文件的过程称为链接,链接后将生成可执行或者库。下面通过观察处理的中间代码(CISO)建立编译过程的直观感受:

假如我编辑并保存了如下程序

//gcctest.cpp
#include <iostream>
using namespace std;
#define AAA 33333

int main()
{
    double a=3.14;//ordinary variable
    double &r=a;//ordinary referenece
    cout<<r<<endl;//read ok
    r=41.3;//write ok
    cout<<r<<endl;
    cout<<AAA<<endl;

    double b=3.14;
    const double &rr =b;//read only, restrict its own right
    cout<<rr<<endl;//read ok
    //rr=41.3;//write not ok
    //cout<<rr<<endl;

    const double c=3.14;
    // double &rrr=c;//reference trying to obtain read and write right failed
    // cout<<rrr<<endl;
    // rrr=41.3;
    // cout<<rrr<<endl;

    const double d=3.14;
    const double &rrrr=d;
    cout<<rrrr<<endl;
    //rrrr=41.3;
    //cout<<rrrr<<endl;
}
3.1 预处理 -E(Pre-pocessing)xxx.c->xxx.i

预处理会做三件事情,为编译做准备:

  • 宏变量替换
  • 头文件展开
  • 注释去除
    命令格式:gcc -E xxx.c
g++ gcctest.cpp -o app.i

这个-o其实指定生成文件名字标识(不指定默认生成a.out

这一阶段生成的文件(xxx.i),还是可以很容易阅读:

//...头文件展开部分

using namespace std;

int main()
{
    double a=3.14;
    double &r=a;
    cout<<r<<endl;
    r=41.3;
    cout<<r<<endl;
    cout<<33333<<endl;

    double b=3.14;
    const double &rr =b;
    cout<<rr<<endl;



    const double c=3.14;





    const double d=3.14;
    const double &rrrr=d;
    cout<<rrrr<<endl;




}
3.2 编译 -S(Compiling) xxx.i->xxx.s

编译过后的文件称为汇编文件。命令格式:g++ xxx.i,这里对上一部分的.i文件进行了处理:

g++ app.i -S -o app.s

仍然是个普通的文本文件,不过语言是汇编:

	.file	"class0919.cpp"
	.text
	.section	.rodata
	.type	_ZStL19piecewise_construct, @object
	.size	_ZStL19piecewise_construct, 1
_ZStL19piecewise_construct:
	.zero	1
	.local	_ZStL8__ioinit
	.comm	_ZStL8__ioinit,1,1
	.text
	.globl	main
	.type	main, @function
main:
.LFB1493:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$80, %rsp
//... 省略了一大段汇编语言
.LC1:
	.long	1717986918
	.long	1078240870
	.hidden	__dso_handle
	.ident	"GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"
	.section	.note.GNU-stack,"",@progbits
3.3 汇编 -c(Assembling) xxx.s->xxx.o

汇编文件汇编后的文件类型是一个二进制文件,编译过程中叫做目标文件,基本上人是没法读懂了:

乱码
3.4 链接(Linking) xxx.o->xxx

对目标文件的集合称为可执行文件。命令g++ xxx1.o xxx2.o

g++ -o eee

内容一样是乱码,使用file命令可以查看其类型:

eee: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=06ad229f773d4211a1a47719e43e93cc2886c5c3, not stripped

可以它是一个可执行程序。

四、GCC其他选项

GCC不仅具有编译成可执行的功能,还具有添加有用信息(-g)和打印信息(调试),甚至还可以调节优化等级(-On)。

optionmeaning
-o指定生成的文件名
-E仅执行编译预处理
-S将C代码转换为汇编代码
-wall显示警告信息
-c仅执行编译操作,不进行连接操作
-g生成调试信息,不加选项不能进行gdb调试

查看GCC版本:

gcc --version
gcc -v

五、常见应用

5.1 无选项编译

无选项编译直接生成名为a.out的可执行文件

gcc test.c

将test.c预处理、汇编、编译并链接成可执行文件a.out

5.2 选项 -o
gcc test.c -o test #省略了-c选项,完整的gcc -c test.c -o test,不会产生中间文件

和无选项编译一样,只不过生成的可执行名字变成了test

5.3 选项 -E

仅预处理:

gcc -E test.c -o test.i

将test.c预处理输出test.i文件。

5.4 选项 -c

仅编译:

gcc -c test.s

将汇编输出文件test.s编译输出test.o文件。

5.5 选项 -S

仅汇编:

gcc -S test.i

将预处理输出文件test.i汇编成test.s文件。

5.6 选项-O

优化选项:

gcc -O1 test.c -o test

使用编译优化级别1编译程序。级别为1~3,级别越大优化效果越好,但编译时间越长

5.7 多个文件一起编译

第一次生成可以使用:

gcc testfun.c test.c -o test

一起编译+链接生成test可执行

仅对部分源文件进行了修改,使用-o选项更快:

gcc -c testfun.c    #将testfun.c编译成testfun.o
gcc -c test.c       #将test.c编译成test.o
gcc -o testfun.o test.o -o test    #将testfun.o和test.o链接成test

[1] 20220622,将原有的文字部分改成流程图

  • 3
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值