GCC快速入门

目的

GCC(GNU Compiler Collection)是GNU出品的用来编译 C、C++、Objective-C、Fortran、Ada、Go 等语言的一系列编译器集合。GCC里面最常用的就是gcc和g++两个工具了,主要用来编编译C和C++的程序,这篇文章将对相关内容做个说明。

基础使用

通常我们使用gcc来编译C语言程序,首先准备下面代码,将它保存为hello.c文件:

#include <stdio.h>

int main(void)
{
	printf("Hello, world!\n");
}

在Linux(这里使用树莓派进行演示,在Windows上可以安装 Mingw-w64 进行测试)上直接使用gcc hello.c就可以编译生成可执行文件:
在这里插入图片描述
上面演示中直接一步到位出成果,但实际上这中间涉及了好几个步骤。C/C++从程序文本经由编译器处理成为目标文件的步骤主要是下面几个:
在这里插入图片描述
可以使用一些选项来控制这些过程:

选项功能
-E预处理指定的源文件,不进行编译
-S编译指定的源文件,但是不进行汇编
-c编译、汇编指定的源文件,但是不进行链接
-o指定生成文件的文件名

在这里插入图片描述
在这里插入图片描述
如果源程序有语法错误那么在编译过程中会报错:
在这里插入图片描述
如果一个程序代码使用了多个文件那么也可以在指定这多个文件进行编译:
在这里插入图片描述
通常来说多个文件编译的时候头文件不需要指定,就像上面例子(不过这样做在某些情况下会有问题,比如头文件中定义的参数改变时)。另外可以用 * 作为通配符,比如 *.c 就是指定所有 .c 文件:
在这里插入图片描述

常用方式
使用gcc一步到位方式编译时每次进行所有文件都需要经历预处理、编译、汇编、链接几个环节,这在文件多的情况下会非常耗时。如果程序经常修改,每次所有文件都需要重复上面过程的话会非常浪费时间。通常情况下我们将整个过程拆分成两步:

  • 使用 -c 选项生成 *.o 的文件;
  • 链接生成目标文件;

这样的话每次只需要对有修改的文件使用 -c 选项生成 *.o 的文件,然后再链接就行,其它没修改的文件就不需要再预处理、编译、汇编了,对大项目来说可以节省很多时间。

C/C++混合编译

上面演示了gcc编译C程序,而对于C++程序我们可以用g++来编译:
在这里插入图片描述
C++是向下兼容的C语言的,所以g++也可以用来编译C程序:
在这里插入图片描述
理论上对于C/C++混合程序而言理论上可以全都用g++来编译,但这样做对程序体积、性能等会有影响,甚至可能会编译出错,所以通常的处理方式如下:

  • 声明C语言程序的头文件中内容使用 extern “C” { } 包围,比如下面这样;
    #ifndef __MYFILE_H__ 
    #define __MYFILE_H__
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    void myfun(void);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif // __MYFILE_H__ 
    
  • 使用gcc -c编译.c文件;
  • 使用g++ -c编译.cpp文件;
  • 使用g++链接生成目标文件;

在这里插入图片描述

反过来C中也可以调用C++中的函数,只需要使用 extern “C” 作为前缀来修饰导出这些函数即可。但是导出的函数必须符合C语言函数的规则,比如重载函数或是类成员函数就需要使用一层符合C语言规范的函数来包围。

静态链接库和动态链接库

一般来说我们写代码时调用的那些系统中自带的库函数都不是.c或是.cpp这些明文的文件,而是一个个封装起来的库文件,通常分为两类:

静态链接库

静态链接库实现链接操作的方式很简单,即程序文件中哪里用到了库文件中的功能模块,GCC 编译器就会将该模板代码直接复制到程序文件的适当位置,最终生成可执行文件。
使用静态链接库生成的文件通常体积较大,但运行时不再依赖库文件,可以拷贝到别的设备上运行。
在Linux中静态链接库文件的后缀名通常用.a表示;在Windows系统中,静态链接库文件的后缀名为.lib。

动态链接库

动态链接库,又称为共享链接库。和静态链接库不同,采用动态链接库实现链接操作时,程序文件中哪里需要库文件的功能模块,GCC 编译器不会直接将该功能模块的代码拷贝到文件中,而是将功能模块的位置信息记录到文件中,直接生成可执行文件。
使用动态链接库生成的文件通常体积较小,但运行时依赖库文件。
在Linux中,动态链接库的后缀名通常用.so 表示;在Windows系统中,动态链接库的后缀名为.dll。

通常情况下GCC在编译过程中默认使用动态链接库,我们可以使用 -static 选项指定使用静态链接库:
在这里插入图片描述
静态链接库和动态链接库我们也可以自己制作,只要是不包含main函数的文件都可以打包成库文件。可以一个文件打包成一个库文件也可以将多个文件打包成一个库文件。

通常可以使用 ar rcs 静态链接库名称 目标文件1 目标文件2 ... 方式将.o文件打包成名称为 libxxx.a 的静态链接库:
在这里插入图片描述
通常可以使用 gcc -fpic -shared 源文件名... -o 动态链接库名 方式将源文件打包成名称为 libxxx.so 的动态链接库(也可以拆分为 gcc -c -fpic ...gcc -shared -o ... 两步;如果编译时出错也可以尝试将 -fpic 换成 -fPIC):
在这里插入图片描述
上面演示中可以看到使用动态链接库生成的程序运行时回去默认的库目录去寻找用到的动态链接库,如果没有找到程序就无法运行。通常Linux中动态链接库放置在/usr/lib/目录下,当我将库移动到该目录下后程序就可以运行了。

一般的像是头文件、库文件的路径或是指定的文件这些都可以手动设置,相关选项如下:

选项功能
-I (大写i)指定头文件路径
-i指定头文件名字
-L指定库文件路径
-l (小写L)指定库文件名字

除了在使用gcc是指定选项的方式,还可以使用环境变量或是配置文件等方式来指定路径和文件。

更多常用选项

对于大型项目来说手动使用GCC来编译其实是很麻烦的,更多的时候会配合Makefile使用,在这个过程中通常还会用到下面这些选项:

选项功能
-M生成文件的依赖信息
-MM生成文件的依赖信息,但忽略由 #include<file>造成的依赖关系
-MD将-M的信息写道.d文件中
-MMD将-MM的信息写道.d文件中
-w不生成任何警告信息
-Wall生成所有警告信息
-Werror将所有警告都当作错误
-O0 -O1 -O2 -O3代码优化等级,-O0表示不优化,-O3表示最高等级优化

总结

GCC基础使用是比较简单的,基本上直接使用是比较少的,通常会配合Makefile使用。而Makefile文件的编写则需要稍稍对GCC的基础使用有一些了解,基本上了解上面那些内容就够了。

更多内容可以参考下面链接:
https://www.gnu.org/software/gcc/

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Naisu Xu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值