使用gcc编译程序过程详解

1.gcc简介

GNU CC(通常简称GCC)是GNU项目的编译器,它能够编译C、C++语言编写的程序。
gcc是Linux开发的基础,gcc能够支持多种不同的C语言版本,同时提供Linux、Unix、Windows下的编译版本。
使用gcc,程序员可以对编译过程有更多的控制,编译过程分为3个阶段:

  • 预处理;
  • 汇编;
  • 链接。
    程序员可以再编译的任何阶段结束后停止整个编译过程以检查编译器在该阶段输出的信息。
    使用gcc,程序员可以控制生成二进制执行文件中调试代码的数量和类型。
    和其他编译器一样,gcc也可以优化执行代码。
    gcc是个交叉平台编译器,所以能够在当前CPU平台上为不同操作系统开发软件。
    gcc对C和C++进行了一些扩展,有助于提高执行效率以及编译器进行代码优化。
    gcc可以让跨平台编程更加容易,降低代码移植代价。
    下面详细将gcc编译的3个阶段。

2.预处理

先给出一段简单的例子代码add.c:

#include <stdio.h>
#include <stdlib.h>
int main(int arg, char *args[])
{
	if (arg < 3)
		printf("请输入2个参数\n");
	else
	{
		int a = atoi(args[1]);
		int b = atoi(args[2]);
		printf("%d 加 %d 等于 %d\n", a, b, a + b);
	}
	return 0;
}

在Linux终端下键入命令:
gcc -o add1.c -E add.c
这行命令告诉gcc对源程序add.c进行预编译,预编译结果输出到add1.c文件中。
这个过程发生了什么呢?
使用cat命令打开add1.c和add.c这两个文件对比看看就知道了:

在这里插入图片描述
上图中左边是预处理后的add1.c,右边是源代码文件add.c。可以看出来,预处理后的add1.c中的两个头文件包含:
#include <stdio.h>
#include <stdlib.h>
找不到了,取而代之的很长的一坨代码。其实,gcc在预处理中做的工作很简单,就是把包含的头文件stdio.h和stdlib.h的内容原封不动的复制到add.c中的#include的位置。
查看stdio.h和stdlib.h文件的内容,在Linux下可以这样看:
cd /usr/include
cat stdio.h
就可以看到了。

3.编译

在Linux下键入命令:
gcc -o add.o -c add1.c
这行命令告诉gcc对源程序add1.c进行编译,但不链接,编译输出到add.o文件中。编译完后的add.o还不能运行,因为程序中调用了例如printf()函数、atoi()函数,这些函数并没有在我们的程序中实现。
当有多个c文件时,都要把c文件编译成.o文件,供后面链接使用。
为了方便演示,编译这里使用代码:
pub.h文件:

#ifndef PUB_H_
#define PUB_H_

int add(int a, int b);

#endif /* PUB_H_ */

pub.c文件:

int add(int a, int b)
{
	return a + b;
}

main.c

#include <stdio.h>
#include "pub.h"

int main(int arg, char *args[])
{
	printf("add = %d\n", add(12, 56));
	return 0;
}

Linux下执行命令:
gcc -o add.o -c pub.c
gcc -o main.o -c main.c
./main.o
后发现:
在这里插入图片描述
这时还需要把程序中用到的.o文件链接起来。

4.链接

在Linux下键入命令链接3编译完的中间文件:
gcc -o mainc add.o main.o
这行命令告诉gcc对源程序main.o和add.o进行链接,生成可执行程序mainc。
在这里插入图片描述
有趣的事来了,当把pub.c改成pub.cpp时,即文件包括:
在这里插入图片描述
把pub.cpp编译成.o中间文件:
gcc -o add.o -c pub.cpp
在这里插入图片描述
再链接:
gcc -main add.o main.o
报错了。。。
在这里插入图片描述
main.c中找不到add()函数的定义。但add()函数明明已经定义了。。。

这是因为gcc默认只链接c编译的库或中间文件,当需要链接cpp编译的中间文件时,gcc需要加–lstdc++明确指出链接C++库:
gcc –lstdc++ -o main add.o main.o

我们使用nm命令看看,gcc编译链接纯c生成的可执行文件:
在这里插入图片描述
使用nm命令看看,gcc编译链接c++生成的可执行文件:
在这里插入图片描述
发现gcc编译纯c的代码时,可执行程序中的函数跟源代码中的函数名是一样的,但gcc编译c++代码时,可执行程序中的函数跟源代码中的函数名是不一样的。这个使用c++函数重载引起的。这个也是为什么dll库、so库的导出函数要用c来写,而不能用c++写,因为c++编译打包后导出函数的名变了,再按原来的导出函数名调用找不到那个函数了,而c就不会。

5.总结

使用gcc编译程序分几步:
预编译源代码;
编译目标代码;
链接中间文件,生成可执行程序或库。
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值