侧边栏壁纸
Linux入门自学网博主等级

每日学一条Linux命令,终成Linux大神

  • 累计撰写 725 篇文章
  • 累计创建 143 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Linux gcc命令教程:如何使用 gcc 编译、链接和调试 C/C++ 程序(附实例详解和注意事项)

Linux gcc命令介绍

gcc 是 GNU Compiler Collection(GNU 编译器集合)的缩写,它是一个开源的、跨平台的、支持多种语言的编译器,包括 C、C++、Objective-C、Fortran、Ada、Go 等。gcc 可以将源代码编译成目标代码,也可以将目标代码链接成可执行文件或者库文件。gcc 是 Linux 系统下最常用的 C/C++ 编译器,大部分 Linux 发行版中都会默认安装。

Linux gcc命令适用的Linux版本

gcc 命令适用于几乎所有的 Linux 发行版,包括 Ubuntu、Debian、Fedora、CentOS、Red Hat、SUSE 等。如果你的系统没有安装 gcc,你可以使用系统自带的包管理工具来安装,例如:

  • 在 Ubuntu 或 Debian 系统中,你可以使用 apt 命令来安装 gcc:
[linux@bashcommandnotfound.cn ~]$ sudo apt update
[linux@bashcommandnotfound.cn ~]$ sudo apt install gcc
  • 在 Fedora 或 CentOS 或 Red Hat 系统中,你可以使用 yum 或 dnf 命令来安装 gcc:
[linux@bashcommandnotfound.cn ~]$ sudo yum update
[linux@bashcommandnotfound.cn ~]$ sudo yum install gcc

或者

[linux@bashcommandnotfound.cn ~]$ sudo dnf update
[linux@bashcommandnotfound.cn ~]$ sudo dnf install gcc
  • 在 SUSE 系统中,你可以使用 zypper 命令来安装 gcc:
[linux@bashcommandnotfound.cn ~]$ sudo zypper update
[linux@bashcommandnotfound.cn ~]$ sudo zypper install gcc

Linux gcc命令的基本语法

gcc 命令的基本语法格式如下:

gcc [options] file...

其中,options 是编译选项,可以指定编译的模式、优化级别、输出文件名等;file 是要编译的源文件,可以是 C、C++ 或其他语言的文件,也可以是目标文件或库文件。

Linux gcc命令的常用选项或参数说明

gcc 命令有很多选项,可以控制编译的过程和结果。下面列举一些常用的选项:

选项说明
-E只进行预处理,不进行编译、汇编和链接
-S只进行预处理和编译,生成汇编代码文件
-c只进行预处理、编译和汇编,生成目标文件
-o file指定输出文件的名称,如果省略,则默认为 a.out
-g生成调试信息,方便使用 gdb 等调试工具
-O0, -O1, -O2, -O3指定编译器的优化级别,-O0 表示不优化,-O3 表示最高级别的优化
-Wall显示所有的警告信息
-I dir指定头文件的搜索路径,dir 是目录名称
-L dir指定库文件的搜索路径,dir 是目录名称
-l name指定要链接的库文件的名称,name 是库文件去掉 lib 前缀和 .a 或 .so 后缀的部分
-D name定义一个宏,相当于在源代码中使用 #define name
-D name=defn定义一个宏,相当于在源代码中使用 #define name defn
-U name取消一个宏的定义,相当于在源代码中使用 #undef name
-std=standard指定编译器使用的语言标准,例如 -std=c99 表示使用 C99 标准
-v显示编译器的版本信息和编译过程
-h 或 --help显示编译器的帮助信息

Linux gcc命令的实例

下面给出一些 gcc 命令的实例,假设有一个 C 源文件 hello.c,内容如下:

#include <stdio.h>
int main(void) {
  printf("Hello, world!\n");
  return 0;
}

实例1:编译并运行 C 程序

如果要编译并运行 hello.c 程序,可以使用以下命令:

[linux@bashcommandnotfound.cn ~]$ gcc hello.c -o hello # 编译并生成可执行文件 hello
[linux@bashcommandnotfound.cn ~]$ ./hello # 运行 hello 程序
Hello, world!

实例2:查看预处理结果

如果要查看预处理的结果,可以使用 -E 选项,并将输出重定向到一个文件中,例如:

[linux@bashcommandnotfound.cn ~]$ gcc -E hello.c -o hello.i # 预处理并生成 hello.i 文件
[linux@bashcommandnotfound.cn ~]$ cat hello.i # 查看 hello.i 文件的内容
# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 424 "/usr/include/features.h" 3 4
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 442 "/usr/include/sys/cdefs.h" 3 4
# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 443 "/usr/include/sys/cdefs.h" 2 3 4
# 425 "/usr/include/features.h" 2 3 4
# 448 "/usr/include/features.h" 3 4
# 1 "/usr/include/gnu/stubs.h" 1 3 4
# 10 "/usr/include/gnu/stubs.h" 3 4
# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 11 "/usr/include/gnu/stubs.h" 2 3 4
# 449 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4

... 省略部分内容 ...

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

实例3:查看汇编代码

如果要查看汇编代码,可以使用 -S 选项,并指定输出文件的名称,例如:

[linux@bashcommandnotfound.cn ~]$ gcc -S hello.c -o hello.s # 编译并生成汇编代码文件 hello.s
[linux@bashcommandnotfound.cn ~]$ cat hello.s # 查看 hello.s 文件的内容
	.file	"hello.c"
	.section	.rodata
.LC0:
	.string	"Hello, world!"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
...

实例4:生成目标文件

如果要生成目标文件,可以使用 -c 选项,并指定输出文件的名称,例如:

[linux@bashcommandnotfound.cn ~]$ gcc -c hello.c -o hello.o # 编译并生成目标文件 hello.o
[linux@bashcommandnotfound.cn ~]$ file hello.o # 查看 hello.o 文件的类型
hello.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

实例5:链接多个目标文件

如果要链接多个目标文件,可以将它们一起作为输入文件,例如:

[linux@bashcommandnotfound.cn ~]$ gcc hello.o world.o -o hello_world # 链接 hello.o 和 world.o 并生成可执行文件 hello_world
[linux@bashcommandnotfound.cn ~]$ ./hello_world # 运行 hello_world 程序
Hello, world!

实例6:链接静态库文件

如果要链接静态库文件,可以使用 -l 选项,并指定库文件的名称,例如:

[linux@bashcommandnotfound.cn ~]$ gcc hello.c -o hello -lmath # 链接 libmath.a 并生成可执行文件 hello
[linux@bashcommandnotfound.cn ~]$ ./hello # 运行 hello 程序
Hello, world!

实例7:链接动态库文件

如果要链接动态库文件,可以使用 -l 选项,并指定库文件的名称,例如:

[linux@bashcommandnotfound.cn ~]$ gcc hello.c -o hello -lncurses # 链接 libncurses.so 并生成可执行文件 hello
[linux@bashcommandnotfound.cn ~]$ ./hello # 运行 hello 程序
Hello, world!

实例8:生成调试信息

如果要生成调试信息,可以使用 -g 选项,并使用 gdb 等调试工具来调试程序,例如:

[linux@bashcommandnotfound.cn ~]$ gcc -g hello.c -o hello # 编译并生成带有调试信息的可执行文件 hello
[linux@bashcommandnotfound.cn ~]$ gdb hello # 使用 gdb 调试 hello 程序
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
... 省略部分内容 ...
Reading symbols from hello...done.
(gdb) break main # 在 main 函数处设置断点
Breakpoint 1 at 0x40054c: file hello.c, line 3.
(gdb) run # 运行程序
Starting program: /home/linux/hello 

Breakpoint 1, main () at hello.c:3
3	  printf("Hello, world!\n");
(gdb) next # 执行下一条语句
Hello, world!
4	  return 0;
(gdb) quit # 退出 gdb
A debugging session is active.

	Inferior 1 [process 1234] will be killed.

Quit anyway? (y or n) y

实例9:指定编译器的优化级别

如果要指定编译器的优化级别,可以使用 -O0, -O1, -O2, -O3 选项,其中 -O0 表示不优化,-O3 表示最高级别的优化,例如:

[linux@bashcommandnotfound.cn ~]$ gcc -O0 hello.c -o hello # 编译并生成不优化的可执行文件 hello
[linux@bashcommandnotfound.cn ~]$ gcc -O3 hello.c -o hello # 编译并生成最高级别优化的可执行文件 hello

实例10:显示所有的警告信息

如果要显示所有的警告信息,可以使用 -Wall 选项,例如:

[linux@bashcommandnotfound.cn ~]$ gcc -Wall hello.c -o hello # 编译并显示所有的警告信息
hello.c: In function ‘main’:
hello.c:4:3: warning: implicit declaration of function ‘puts’ [-Wimplicit-function-declaration]
   puts("Hello, world!");
   ^~~~

实例11:指定头文件的搜索路径

如果要指定头文件的搜索路径,可以使用 -I 选项,并指定目录的名称,例如:

[linux@bashcommandnotfound.cn ~]$ gcc -I /home/linux/include hello.c -o hello # 编译并指定头文件的搜索路径为 /home/linux/include

实例12:指定库文件的搜索路径

如果要指定库文件的搜索路径,可以使用 -L 选项,并指定目录的名称,例如:

[linux@bashcommandnotfound.cn ~]$ gcc -L /home/linux/lib hello.c -o hello -lmath # 编译并指定库文件的搜索路径为 /home/linux/lib

实例13:定义和取消宏

如果要定义和取消宏,可以使用 -D 和 -U 选项,例如:

[linux@bashcommandnotfound.cn ~]$ gcc -D DEBUG -D PI=3.14 -U DEBUG hello.c -o hello # 编译并定义 DEBUG 和 PI=3.14,取消 DEBUG

实例14:指定编译器使用的语言标准

如果要指定编译器使用的语言标准,可以使用 -std 选项,并指定标准的名称,例如:

[linux@bashcommandnotfound.cn ~]$ gcc -std=c99 hello.c -o hello # 编译并使用 C99 标准

实例15:显示编译器的版本信息和编译过程

如果要显示编译器的版本信息和编译过程,可以使用 -v 选项,例如:

[linux@bashcommandnotfound.cn ~]$ gcc -v hello.c -o hello # 编译并显示版本信息和编译过程
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
...

Linux gcc命令的注意事项

在使用 gcc 命令时,有一些注意事项需要了解,例如:

  • gcc 命令默认会使用 C 语言来编译源文件,如果要使用其他语言,例如 C++,需要使用 g++ 命令,或者使用 -x 选项来指定语言类型,例如:
[linux@bashcommandnotfound.cn ~]$ g++ hello.cpp -o hello # 使用 g++ 命令来编译 C++ 源文件
[linux@bashcommandnotfound.cn ~]$ gcc -x c++ hello.cpp -o hello # 使用 gcc 命令并指定语言类型为 c++
  • gcc 命令会根据源文件的扩展名来判断文件的语言类型,例如 .c 表示 C 语言,.cpp 表示 C++ 语言,.s 表示汇编语言等。如果源文件没有扩展名,或者扩展名不符合规范,需要使用 -x 选项来指定语言类型,例如:
[linux@bashcommandnotfound.cn ~]$ gcc -x c hello -o hello # 编译没有扩展名的 C 源文件
[linux@bashcommandnotfound.cn ~]$ gcc -x assembler hello.s -o hello # 编译有扩展名的汇编源文件
  • gcc 命令在编译时会自动链接一些标准库,例如 libc、libm 等,如果要链接其他的库,需要使用 -l 选项,并注意库文件的顺序,一般来说,被依赖的库文件应该放在后面,例如:
[linux@bashcommandnotfound.cn ~]$ gcc hello.c -o hello -lncurses -lm # 链接 libncurses.so 和 libm.a,注意 libm.a 要放在后面,因为 libncurses.so 依赖于 libm.a
  • gcc 命令在编译时会在当前目录下生成一些临时文件,例如 .i、.s、.o 等,如果不需要保留这些文件,可以使用 -save-temps 选项,并指定输出目录,例如:
[linux@bashcommandnotfound.cn ~]$ gcc -save-temps=obj hello.c -o hello # 编译并将临时文件保存在 obj 目录下
  • gcc 命令在编译时可能会出现一些错误或警告信息,如果要忽略这些信息,可以使用 -w 选项,例如:
[linux@bashcommandnotfound.cn ~]$ gcc -w hello.c -o hello # 编译并忽略所有的错误和警告信息
  • 如果在使用 gcc 命令时出现 bash: gcc: command not found 的错误,说明系统没有安装 gcc 编译器,需要使用系统自带的包管理工具来安装,具体的安装命令请参考上面的 Linux gcc命令适用的Linux版本 一节。

Linux gcc相关命令

除了 gcc 命令之外,还有一些与 gcc 相关的命令,可以用来执行一些特定的任务,例如:

2

评论区