gcc
是Linux世界中非常流行的编译器。 gcc
为C、C++、java等编程语言提供解释器和编译器等。在本教程中,我们将研究流行的编译器选项,如错误、预处理器、输出、优化等。
示例C应用程序代码
在本教程中,我们将使用以下简单的示例代码。我们可以看到这个代码只打印出来 HELLO POFTUT.COM
到标准输出。
#include<stdio.h> int main(void) { printf("HELLO POFTUT.COM"); return 0; }
指定输出可执行文件名
gcc的默认行为是将编译的可执行文件作为 a.out
. 这可能不适合专业工作的漂亮解决方案。我们可以使用 -o
通过显式提供可执行文件名。在本例中,我们将可执行文件名设置为 app
.
$ gcc -o app main.c

我们可以使用 file
将打印的命令
- 文件类型
- 建筑
- 版本
- 构建ID
稍微优化一下
优化通常会使创建的二进制文件运行得更快。我们可以用 -O1
选项,以优化一点。
$ gcc -O1 main.c
优化更多
更多的优化意味着更快的速度。在大多数情况下,这是2级优化和最佳选择。
$ gcc -O2 main.c
综合优化
互补优化将使我们的二进制更快,但这可能不工作,在某些情况下。相应地使用此优化级别。我们将使用 -O3
选项。
$ gcc -O3 main.c
优化大小
在嵌入式系统中,磁盘大小可能是个问题。我们可能需要以大小优化的方式编译整个库或框架。所以我们可以使用 0s
选项,该选项将减小创建的二进制可执行文件的大小。
$ gcc -Os -o main main.c

我们可以看到截图中的差异是优化前的大小 8.2K
但经过优化后,其性能下降到原来的水平 8.1K
.
启用所有编译警告
默认情况下,不显示警告。但这可能会隐藏有关代码质量和安全性的问题。我们可以使用 -Wall
选项。此选项是合并或警告全部。我们将使用以下代码创建一些警告。
#include<stdio.h> int main(void) { int a; printf("HELLO POFTUT.COM [%d]",a); return 0; }
我们将使用以下命令编译。
$ gcc -Wall main.c

我们可以看到这个变量 a
在没有显式值的情况下未初始化和使用。
相关文章: 如何在终端和SSH示例中安装和使用Cygwin?
不要只编译预处理
据我们所知 gcc
在3个阶段编译C应用程序。第一阶段是预处理。我们可以在预处理后停止编译操作,并中断编译操作。我们将使用 -E
获取预处理文件但创建输出的选项将放在标准输出中。所以我们将把这个输出重定向到一个名为 main.i
. 预处理的文件 *.i
扩展。
$ gcc -E main.c > main.i

我们打印前10行 main.i
具有 head
命令。
仅生成程序集代码
C应用程序编译的第二阶段是从前一阶段生成的预处理代码生成汇编代码。我们可以用 -S
选项并重定向到名为 main.s
$ gcc -S main.c > main.s

因为我们已经用 head
我们可以看到装配说明。
只生成编译代码
我们只能用 -C
选项。这将只包含机器级代码 没有任何联系。
$ gcc -C main.c

生成所有中间步骤文件,如预处理、组装
正如我们之前所看到的,编译过程中有几个阶段。默认情况下,会自动删除中间文件或临时文件。如果我们想检查这些文件而不删除它们,我们可以使用 -save-temps
不删除预处理文件和程序集文件的选项。
$ gcc -save-temps main.c

我们也可以列出这些文件 file
命令如下。
$ file main.*
与共享库链接
如果我们要使用外部共享库,我们需要将它们链接到可执行文件。我们可以将共享库与 -l
选项并提供不带任何扩展名的库名称。例如,如果我们想使用名为 abc.so
我们将使用以下 gcc
命令。
$ gcc -labc -o main main.c
产生与记忆位置无关的代码
创建共享库时,程序集代码位置受到保护。我们可以用 -fPIC
选项如下。
$ gcc -fPIC -o main main.c
打印编译操作的所有中间步骤
正如我们所看到的,编译操作中有中间步骤和过程。我们可以使用 -v
选项。
$ gcc -v main.c

我们看到这样的信息:;
- 目标
- 线程模式
- gcc版本
- gcc选项
- gcc汇编程序版本
- …
相关文章: CMake教程在Linux中构建和编译
提供
启用ANSI/ISO C89支持
C语言有不同的版本和标准,由ANSI或ISO制定。我们可以在编写过程中严格执行这些标准。例如,我们可以使用 -ansi
选项如下。
$ gcc -ansi main.c
将字符解释为无符号字符
char
C编程语言中的类型在编译操作期间提供了一些灵活性。我们可以根据给定的gcc选项对它们进行不同的解释。我们可以解释 char
变量类型为 unsigned char
具有 -funsigned-char
选项。
$ gcc -funsigned-char main.c
将字符解释为有符号字符
另一个选择 char
类型用法为 signed char
. 我们可以解释 char
将变量键入为 signed char
具有 -fsigned-char
就像下面一样。
$ gcc -fsigned-char main.c
使用编译时宏
宏提供了将编译时操作注入源代码的能力。只需使用给定的宏选项编译宏部件。在本例中,我们将使用 -D
宏名称为 MYMACRO
.
#include<stdio.h> int main(void) { #ifdef MYMACRO printf("MYMACRO"); #endif printf("HELLO POFTUT.COM "); return 0; }
我们会跟着 gcc
命令。
$ gcc -DMYMACRO -o main main.c

将警告解释为错误
错误是中断编译的情况。另一方面,警告不会中断编译过程,只是提供一些有关情况的信息。我们可以做 gcc
解释错误等警告并中断编译 -Werror
选项。
$ gcc -Werror -o main main.c
从文件中提供gcc选项
到目前为止,我们已经提供了 gcc
以交互方式从命令行中选择选项。我们还可以从文件或批处理文件中提供这些选项。这将使 gcc
如果我们有 有很多选择。我们将使用 @
在选项文件之前签名。我们将在名为 opt
.
-Werror -v -DMYMACRO
我们将编译如下。
$ gcc @opt -o main main.c
