GCC如何编译c程序及流程分析
更新时间:2021年4月11日11:13:50 提交:mdxy-dxy
目前Linux下最常用的C语言编译器是GCC(GNUCompilerCollection)。 它是GNU项目中符合ANSIC标准的编译系统。 它可以编译C、C++、ObjectC等语言编译的程序。
目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection)。 它是GNU项目中的一个符合ANSIC标准的编译系统程序编译网站,可以编译C、C++、ObjectC等语言编译的程序。 GCC除了功能强大之外,结构上也极其灵活。 最难能可贵的是它可以通过不同的后端模块支持各种语言,比如Java、Fortran、Pascal、Modula-3和Ada等。开放、自由、灵活是Linux的魅力,而这在GCC中得到了体现,这意味着程序员可以更好地控制整个编译过程。 使用GCC编译程序时,编译过程可以细分为四个阶段:
预处理
编译
组装
Linux程序员可以根据自己的需要让GCC在编译的任意阶段结束,从而检测或利用编译器在该阶段的输出信息,或者控制最终生成的二进制补码文件,以方便添加不同的数字和类型。 调试代码,为以后的调试做准备。 与其他常用的编译器一样,GCC也提供了灵活而强大的代码优化功能,可以生成执行效率更高的代码。
GCC 提供了 30 多种警告消息和三个警告级别。 使用它们有助于提高程序的稳定性和可移植性。 据悉,GCC还对标准C和C++语言进行了大量扩展,以提高程序执行效率,帮助编译器优化代码,减少编程工作量。
C程序的编译过程主要分为四个阶段:预处理、编译、汇编、链接;
常用的文件扩展名:
gcc预处理阶段:主要处理包含的头文件(#include)和宏定义(#define、#ifdef...)。 可以使用“gcc -E”让gcc在预处理后停止编译过程并生成*.i文件。
[root@localhostgcc]#gcc-Ehello.c-ohello.i
gcc编译阶段:gcc首先需要检测代码的规范性以及是否存在句型错误等。为了确定代码实际做了什么,测试正确后gcc将代码翻译成汇编语言。用户可以使用- S选项查看,只进入
没有汇编的行编译会生成汇编代码。
[root@localhostgcc]#gcc-Shello.i-ohello.s
gcc汇编阶段:生成目标代码*.o; 有两种方法:使用gcc直接从源代码生成目标代码gcc-c*.so*.o和使用汇编器从汇编代码生成目标代码as*.so*。 哦
[root@localhostgcc]#gcc-chello.s-ohello.o
[root@localhostgcc]#ashello.s-ohello.o
也可以直接使用as*.s执行汇编链接过程,生成可执行文件a.out。 您可以像以前一样使用 -o 选项指定输出文件的格式。
gcc链接阶段:生成可执行文件; 可以生成的可执行文件格式有:a.out/*/,其实还可能有其他格式。
[root@localhostgcc]#gcchello.o 生成可执行文件a.out
[root@localhostgcc]#gcchello.o-ohello 生成可执行文件 hello
常见的gcc编译选项:
-Dmacro 定义指定的宏,这样也可以在源码中通过#ifdef检查;
-O、-O2、-O3 打开优化状态。 该选项不能与-g选项一起使用;
-v 激活所有警报并复制有关编译过程的信息;
-Wall在发生报警时取消编译操作,官方报警视为错误;
-Werror 发生报警时取消编译操作,即认为报告有错误;
-w 严格禁止所有报告。
gcc链接库文件的使用
在Linux下开发软件时,完全不使用第三方函数库的情况很少见。 一般来说,需要借助一个或多个函数库的支持来完成相应的功能。 从程序员的角度来看,函数库实际上是头文件(.h)和库文件(.so或.a)的集合。 虽然Linux下的大多数函数默认将头文件放置在/usr/include/目录中,将库文件放置在/usr/lib/目录中,但并非所有情况都是如此。 正因为如此,GCC在编译时必须有自己的方式来查找所需的头文件和库文件。 GCC 使用目录搜索方法来查找所需的文件。 -I选项可以将新目录添加到GCC的头文件搜索路径中。 例如,如果 /home/justin/include/ 目录中有编译所需的头文件,为了让 GCC 成功找到它们,可以使用 -I 选项:
#gccfoo.cI/home/justin/include-ofoo
同样,如果您使用的库文件不在标准位置,则可以使用 -L 选项将新目录添加到 GCC 的库搜索路径中。 例如,如果/home/xiaowp/lib/目录下有需要链接的库文件libfoo.so,为了让GCC顺利找到它,可以使用以下命令:
#gccfoo.cL/home/justin/lib-lfoo-ofoo
值得解释的是 -l 选项,它指示 GCC 链接到库文件 libfoo.so。
Linux下库文件命名有一个约定,就是应该以lib三个字母开头,因为所有的库文件都遵守相同的规范,所以在使用-l选项指定库文件名时可以省略。链接库文件。 lib 三个字母,也就是说GCC处理-lfoo时,会手动链接名字libfoo.so
Linux下的库文件分为两类:动态链接库(一般以.so结尾)和静态链接库(一般以.a结尾)。 两者的区别仅在于程序执行时所需要的代码是否在运行。 是在编译时动态加载还是在编译时静态加载。 默认情况下,GCC在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链接库。 如果需要,可以在编译时添加-static选项,强制使用静态链接库。 例如,如果home/justin/lib/目录下有链接所需的库文件libfoo.so和libfoo.a,为了让GCC在链接时只使用静态链接库,可以使用以下命令:
#gccfoo.cL/home/justin/lib-static-lfoo-ofoo 文件。
关于动态库和静态库文件的创建方法,这里不再详细说明。 关于如何创建linuxc库文件可以参考另一篇文章。
Linux下使用gcc编译运行C/C++程序
编译C
首先,程序编译过程包括:
1.预处理(展开宏、头文件、检测代码错误)
2.编译(将.c转换为汇编代码.s)
3.汇编(将汇编代码.s转换为机器代码.o)
4.链接(将所有机器码.o和库文件链接成可执行程序)
通常编译常包括:预处理、编译、汇编
在Linux系统中,使用gcc编译器编译c,如下:
gcc-outin1.cin2.c//gcc编译链接(编译in1文件和in2文件生成out.bin文件,“-o”:表示生成可执行文件)
gcc-cin1.cin2.c-oout.o //gcc编译无需链接(编译in1文件和in2文件生成out.o文件,
“-c”:表示只生成*.o文件; 第二个“-o”:表示将生成.o文件)
(如果只编译链接单个文件,也可以直接输入:gccin.c,系统默认会编译生成a.out可执行文件)
如果需要在arm板上运行,需要在Linux系统中使用arm-linux-gcc交叉编译:
arm-linux-gcc-outin1.cin2.c//gcc编译链接(编译in1文件和in2文件生成out.bin文件,“-o”:表示生成可执行文件)
arm-linux-gcc-cin1.cin2.c-oout.o//gcc编译无需链接(编译in1文件和in2文件生成out.o文件,
“-c”:表示只生成*.o文件; 第二个“-o”:表示指定生成.o文件)
-I //表示添加的头文件位置
通常编译程序时,如果提示找不到某个头文件,只需在编译时加上“-I 头文件所在目录”,编译就可以了。
-l //指定库文件程序编译网站,l后面是库文件,例如物理库:-lm,对应libm.so文件。 您只需删除 lib 和 .so 即可。
编译程序时,找不到函数定义时,可能是因为没有添加库文件。 例如,如果找不到cos()函数定义,只需在编译时添加“-lm”即可。
编译C++
方法和上一种类似,使用g++编译器,只不过编译器会手动链接C++库
注意:如果需要c++11标准,则需要gcc4.8或以上版本
以编译两个C文件(ac和hello.c)为例:
via.c//编辑ac,会被hello.c调用,前提是两个文件必须在同一目录下
内容如下:
vihello.c//编辑hello.c
内容如下:
gcc-ohellohello.ca.c //gcc编译链接(编译hello.c文件和ac文件生成hello.bin文件,“-o”:表示生成可执行文件)
./hello//运行hello.bin
功效如下:
关于GCC编译c程序的方法和过程分析的这篇文章就到此结束了。 更多关于GCC编译c程序的信息,请搜索Script House之前的文章或者继续浏览下面的相关文章。 希望大家以后能够支持我。 脚本之家!