Linux GCC 编译详解

article/2025/10/5 16:50:06

文章目录

    • 一、GCC 编译器简介
    • 二、GCC 工作流
      • 编程语言的发展
      • GCC 工作流程
      • gcc 和 g++ 的区别
    • 三、使用 GCC 编译
      • GCC 编译格式
      • GCC 编译流程
      • 多个源文件编译

一、GCC 编译器简介

首先,什么是编译器呢?
我们可以使用编辑器(如 linux 下的 vi、windows 下的记事本)来写程序(编辑代码)。但是我们写的程序中的代码语句,电脑是看不懂的,我们需要把它转成电脑能懂的语句,编译器就是这样的转化工具。就是说,我们用编辑器编写程序,由编译器编译后才可以运行!编译器是将易于编写、阅读和维护的高级计算机语言翻译为计算机能解读、运行的低级机器语言的程序

那什么是 GCC 编译器?

  1. gcc(GNU Compiler Collection,GNU 编译器套件),是由 GNU 开发的编程语言编译器。gcc 作为GNU操作系统的官方编译器,现已被大多数类 Unix 操作系统(如Linux、BSD、Mac OS X等)采纳为标准的编译器,gcc 同样适用于微软的 Windows。
  2. gcc 最初用于编译 C 语言,随着项目的发展 gcc 已经成为了能够编译 C、C++、Java、Ada、fortran、Object C、Object C++、Go 语言的编译器大家族。
  3. GCC 常用来编译 C/C++ 语言:
    1. 它不仅支持 C 的许多“方言”,也可以区别不同的 C/C++ 语言标准;
    2. 也可以使用命令行选项来控制编译器在翻译源代码时应该遵循哪个 C/C++ 标准。例如,当使用命令行参数 -std=c99 启动 GCC 时,则编译器支持 C99 标准。

如何安装使用 GCC 呢?
linux ubuntu 下,可以通过 sudo apt install gcc g++ 安装命令安装
查看版本 gcc/g++ -v/–version:

yxm@192:~$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

【注意】如果需要支持 c++11,gcc 版本需要 > 4.8.5。

二、GCC 工作流

编程语言的发展

计算机语言的发展 总体分三个阶段

  • 第一代机器语言:机器语言是微处理器理解和使用的,用于控制它的操作二进制代码。
    • 优点:直接执行,速度快,资源占用少
    • 缺点:可读性、可移植性差,编程繁杂
  • 第二代汇编语言 :一种面向机器的低级语言,通常是为特定的计算机或系列计算机专门设计的。汇编语言是机器指令的符号化表示,故不同的机器就有不同的汇编语言。使用汇编语言能面向机器并较好地发挥机器的特性,得到质量较高的程序。汇编语言虽然能编写高效率的程序,但是学习和使用都不是易事,并且很难调试。
  • 第三代高级语言:高级语言主要是相对于汇编语言而言的,它是较接近自然语言和数学公式的编程,基本脱离了机器的硬件系统,用人们更易理解的方式编写程序。编写的程序称之为源程序

GCC 工作流程

从上面的编程语言的发展过程可以知道,我们现在常说的编程语言一般都是高级语言,编写的程序称之为源程序。编译器其实就相当于一个翻译器,将高级语言翻译成机器语言以便机器可以识别。

gcc 编译器从拿到一个c 源文件到生成一个可执行程序,中间一共经历了四个步骤:
四个步骤并不是 gcc 独立完成的,而是在内部调用了其他工具,从而完成了整个工作流程:
【注意】头文件展开:其实就是把头文件中的内容复制到 .c/.c++ 源代码文件中。

gcc 和 g++ 的区别

理解了 GCC 的工作流程,接下来说一下 gcc 和 g++ 的区别,相信你会有更加深刻的了解。

首先,gcc 和 g++都是GNU(组织)的一个编译器。

误区一:gcc 只能编译 c 代码,g++ 只能编译 c++ 代码。其实两者都可以编译,请注意:

  • 后缀为 .c 的,gcc 把它当作是 C 程序,而 g++ 当作是 c++ 程序;
  • 后缀为 .cpp 的,两者都会认为是 C++ 程序,C++ 的语法规则更加严谨一些。
  • 编译阶段,g++ 会调用 gcc,对于 C++ 代码,两者是等价的,但是因为 gcc 命令不能自动和 C++ 程序使用的库联接,所以通常用 g++ 来完成链接,为了统一起见,干脆编译/链接统统用 g++ 了,这就给人一种错觉,好像 cpp 程序只能用 g++ 似的。

误区二:gcc 不会定义 __cplusplus 宏,而 g++ 会

  • 实际上,这个宏只是标志着编译器将会把代码按 C 还是 C++ 语法来解释
  • 如上所述,如果后缀为 .c,并且采用 gcc 编译器,则该宏就是未定义的,否则,就是已定义

误区三:编译只能用 gcc,链接只能用 g++

  • 严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用 gcc/g++,而链接可以用 g++ 或者 gcc -lstdc++。
  • gcc 命令不能自动和C++程序使用的库联接,所以通常使用 g++ 来完成联接。但在编译阶段,g++ 会自动调用 gcc,二者等价

总结:看到上面的误区,你可能能够理解了,但是使用起来比较晕,那么不妨给自己一个规则:gcc 编译 c 代码,g++ 编译 c++ 代码

三、使用 GCC 编译

GCC 编译格式

首先,了解一下,GCC 编译命令的格式:
命令 选项 输出可执行文件的文件名 文件名
gcc [options] [file] file…
g++ [options] [file] file…

  • 命令、选项和源文件之间使用空格分隔;
  • 一行命令中可以有零个、一个或多个选项;
  • 文件名可以包含文件的绝对路径,也可以使用相对路径;
  • 如果命令中不包含输出可执行文件的文件名,可执行文件的文件名会自动生成一个默认名,Linux平台为a.out,Windows平台为 a.exe

GCC 常用选项

选项作用
-o指定生成的输出文件名为file
【注意】除了上面的编译格式,-o 还可以使用另外一种编译格式,如下所示:
命令 文件名 选项 输出可执行文件的文件名
gcc file… [options] [file]
g++ file… [options] [file]
-E只进行预处理
-S(大写)只进行预处理和编译
-c(小写)只进行预处理、编译和汇编
-v / --version查看gcc版本号
-g包含调试信息,该程序可以被调试器调试
-On n=0~3编译优化,n越大优化得越多。n的取值范围:0~3。编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
-Wall提示更多警告信息
-D编译时定义宏
-L指定编译的时候,搜索的库的路径。
-I directory即指定 include 包含文件的搜索目录
-w不生成任何警告信息
-l在程序编译的时候,指定使用的库
-std指定C方言,如:-std=c99,gcc默认的方言是GNU C
-shared生成共享目标文件,通常用在建立共享库时

【注意】上表中仅列出了常用的一些指令选项,事实上这仅是冰山一角,GCC 编译器提供有大量的指令选项,可满足我们在大部分场景下的编译需求。有关更多的编译指令,感兴趣的读者可自行查看 GCC 手册。

GCC 编译流程

如上面的文章所讲,C 或者 C++ 程序从源代码生成可执行程序的过程,需经历 4 个过程,分别是预处理、编译、汇编和链接。同样,使用 GCC 编译器编译 C 或者 C++ 程序,也必须要经历这 4 个过程。下面以运行 C 语言程序为例,给大家演示如何使用 gcc 快速获得对应的可执行程序。如下就是一段 C 语言程序:

// test.c 文件
#include <stdio.h>
#define PI 3.14
int main() 
{int sum = PI + 10;printf("Hello World\n");return 0;
}
# 第一步: 进行预处理
yxm@192:~$ gcc -E test.c  -o test.i
yxm@192:~$ ls
company_project  install  myshare  test.c  test.i# 第二步: 生成汇编文件
yxm@192:~$ gcc -S test.i  -o test.s
yxm@192:~$ ls
company_project  install  myshare  test.c  test.i  test.s# 第三步: 生成目标代码
yxm@192:~$ gcc -c test.s  -o test.o
yxm@192:~$ ls
company_project  install  myshare  test.c  test.i  test.o  test.s# 第四步: 生成可以执行文件
yxm@192:~$ gcc test.o  -o test
yxm@192:~$ ls
company_project  install  myshare  test  test.c  test.i  test.o  test.s# 第五步: 执行 
yxm@192:~$ ./test
Hello World

但考虑在实际使用中,我们可能并不关心程序的执行结果,只想快速得到最终的可执行程序,因此 gcc 和 g++ 都对此需求做了支持,可以直接将源文件生成一个可以执行文件

yxm@192:~$ gcc test.c  -o test
yxm@192:~$ ls
company_project  install  myshare  test  test.c
yxm@192:~$ ./test
Hello World

可以看到,GCC 编译器支持使用 gcc(g++)指令“一步编译”指定的 C(C++)程序。【注意】虽然我们仅编写了一条 gcc 或者 g++ 指令,但其底层依据是按照预处理、编译、汇编、链接的过程将 C 、C++ 程序转变为可执行程序的。而本应在预处理阶段、编译阶段、汇编阶段生成的中间文件,此执行方式默认是不会生成的,只会生成最终的 a.out 可执行文件。

如果不指定输出文件名字,gcc 编译器会生成一个默认的可以执行文件 a.out

yxm@192:~$ gcc test.c 
yxm@192:~$ ls
a.out  company_project  install  myshare  test.c
yxm@192:~$ ./a.out 
Hello World

gcc -D 选项:下面以运行 C 语言程序为例,给大家演示如何使用 gcc -D 选项的使用。如下就是一段 C 语言程序:

// test.c 
#include <stdio.h>
int main(void)
{int a = 3;
#ifdef DEBUGprintf("hello itcast\n");
#endifprintf("hello world\n");return 0;
}
yxm@192:~$ gcc test.c -DDEBUG
yxm@192:~$ ls
a.out  company_project  install  myshare  test.c
yxm@192:~$ ./a.out 
hello itcast
hello world

我们在工作的时候,软件一般有两个版本,一个发行版本(release 版本),一个是调试版本(debug 版本),如果在编译时指定-D参数(如上所示)就相当于是调试版本,可以打印调试信息;如果在编译时不指定-D参数就相当于发行版本。【补充】release 版本,一般要求我们把调试信息、log 信息等输出信息都删除掉,因为频繁的输出会大大降低程序的执行效率。

我们还可以通过 -D 选项设置宏的值,如下例所示:

// test.c
#include <stdio.h>
int main(void)
{printf("SIZE: %d\n", SIZE);return 0;
}
deng@itcast:~/test$ gcc 2test.c -DSIZE=10
deng@itcast:~/test$ ./a.out
SIZE: 10

多个源文件编译

如果需要编译多个源文件,基本上有两种编译方法,假设有两个源文件为 file1.c 和 file2.c:

  1. 多个文件一起编译
    用法:gcc file1.c file2.c -o file
    作用:将 file1.c 和 file2.c 分别编译后链接成 file 可执行文件。

【注意】此时 file1.c、file2.c 这两个文件没有先后关系,位置随意放置。

  1. 分别编译各个源文件,之后对编译后输出的目标文件进行链接。
    # 用法
    gcc -c file1.c 						# 将file1.c编译成file1.o
    gcc -c file2.c 						# 将test.c编译成file2.o
    gcc -o file1.o file2.o -o file 		# 将file1.o和file2.o链接成file
    # gcc -o *.o -o file 	# 简洁写法,等价于 gcc -o file1.o file2.o -o file
    

总结:以上两种方法相比较,第一种方法编译时需要所有文件重新编译,而第二种方法可以只重新编译修改的文件,未修改的文件不用重新编译


http://chatgpt.dhexx.cn/article/oKWScfmJ.shtml

相关文章

gcc编译命令的常用选项——强烈推荐大家使用 -Wall 选项

C程序编编译的过程分为如下四个阶段 1.预处理&#xff1a;头文件展开&#xff08;#include&#xff09;、宏替换&#xff08;#define&#xff09;、条件编译&#xff08;#ifdef&#xff09;(.i)使用预处理器&#xff08;预处理阶段处理的都是以#开头的代码&#xff09; 2.编译…

Linux(gcc编译原理、过程以及常用调试命令)

PS&#xff1a;红色字体表示重点&#xff0c;绿色字体表示重要标题&#xff0c;块引用中表示Linux终端中的命令。 1.gcc / g的安装 命令&#xff1a;sudo apt install gcc /gcc 2.gcc编译连接 //main.c文件 &#xff08;1&#xff09;预编译 ①删除所有的“#define”&#…

Linux中gcc编译步骤

我们这里以C语言为例&#xff0c;看看C语言程序在Linux中编译执行的详细步骤 1.创建一个.c文件 2.写入一些简单的代码 我们使用gcc -E filename.c -o filename.i 命令对程序先进行预处理&#xff1a;处理头文件、宏定义&#xff0c;接下来我们修改一下头文件&#xff0c;使用错…

Linux GCC常用命令

目录 一、示例一 1.简单编译 1.1预处理 1.2编译为汇编代码 1.3汇编 1.4连接 2.多个程序文件的编译 3检错 4库文件连接 二、示例二 1.准备hello.c 2.预处理 3.编译 4.汇编 5.链接 6.分析ELF文件 6.1ELF文件的段 6.2反汇编ELF 一、示例一 1.简单编译 创建文件mkd…

GCC编译过程及基本命令总结

一、GCC简介 GCC即GNU Compiler Collection&#xff0c;原本只是针对C语言的编译工具&#xff0c;现在已经变成了一个工具集&#xff0c;包含了C、C、JAVA等语言的集合体。 管理和维护&#xff1a;由GNU项目负责。 二、GCC对C、C的编译流程 (1) 预处理&#xff08;Preproce…

Linux 下的 gcc 编译常用命令

gcc&#xff1a;Linux下的一款编译器。 gcc工作流程&#xff1a; 完整编译流程&#xff1a; 创建一个c语言源文件&#xff1a; gcc -E hello.c -o hello.i&#xff08;头文件展开&#xff0c;进行源文件中的宏替换&#xff0c;注释过滤&#xff09; gcc -S hello.i -o hello.…

GCC命令编译

1.GCC编译过程&#xff08;原理如下&#xff0c;使用命令请见2&#xff09; 从 hello.c 到 hello(或 a.out)文件&#xff0c; 必须历经 hello.i、 hello.s、 hello.o&#xff0c;最后才得到 hello(或a.out)文件&#xff0c;分别对应着预处理、编译、汇编和链接 4 个步骤&#…

gcc 命令详解及最佳实践

介绍 GCC&#xff08;英文全拼&#xff1a;GNU Compiler Collection&#xff09;是 GNU 工具链的主要组成部分&#xff0c;是一套以 GPL 和 LGPL 许可证发布的程序语言编译器自由软件&#xff0c;由 Richard Stallman 于 1985 年开始开发。 GCC 原名为 GNU C语言编译器&#…

使用GCC编译程序常用命令

一、编译器驱动程序 首先梳理一下源文件到可执行文件的整个过程&#xff0c;下面是两个源文件的组成main.c和sum.c // main.c int sum(int *a, int n); int array[2] { 1, 2 }; int main() {int val sum(array, 2);return val; }// sum.c int sum(int *a, int n) {int i, s…

matlab 反向二值化,MATLAB:图像二值化、互补图(反运算)(im2bw,imcomplement函数)...

图像二值化、反运算过程涉及到im2bw&#xff0c;imcomplement函数&#xff0c;反运算可以这么理解&#xff1a;原本黑的区域变为白的区域&#xff0c;白的区域变为黑的区域。 实现过程如下&#xff1a; close all;%关闭当前所有图形窗口&#xff0c;清空工作空间变量&#xff0…

图像处理Matlab阈值的设置imadjust(),graythresh(),im2bw()函数使用

1、imadjust()函数调节图像的对比度(若图像较暗&#xff0c;可用imadjust函数命令来调节图像的对比度) I1imadjust(I,stretchlim(I),[0;1]); % stretchlim(I2)自适应找到一个分割阈值向量来改变一幅图像的对比度 figure,imshow(I1); 2、matlab中DIP工具箱函数im2bw使用阈值&…

MATLAB--对于im2bw函数的优化

由于我在研究的是uint8图像&#xff0c;所以对于优化im2bw函数的形式为&#xff1a;im2bw(uint8[], T)&#xff0c;不过其它形式也可以由类似思想导出。 测试代码&#xff1a;遍历8个图像得出时间 for n1:8cchar(str(n));fimread(c);testtime3%要测试的代码 end 算法一 tic fR…

MATLAB中将图像转换为二值图像im2bw

在MATLAB中将图像转换为二值图像&#xff0c;主要运用im2bw函数&#xff0c;涉及到一个灰度门槛的数值。 对于灰度图像 bwim2bw(I,level); level空着的话&#xff0c;默认是0.5。level一般使用graythresh函数来计算&#xff0c;至于graythresh函数中运用到的Otsus method&am…

matlab函数im2bw_图像分割之阈值分割(matlab)(转载)

转载自&#xff1a;https://blog.csdn.net/weixin_39824223/article/details/112249214 matlab函数im2bw_图像分割之阈值分割&#xff08;matlab&#xff09; weixin_39824223 2021-01-02 06:21:09 373 收藏 2 文章标签&#xff1a; matlab函数im2bw 图像分割是一种重要的…

MATLAB中im2bw函数-将图像转换为二值图像

matlab中DIP工具箱函数im2bw使用阈值&#xff08;threshold&#xff09;变换法把灰度图像&#xff08;grayscale image&#xff09;转换成二值图像。所谓二值图像&#xff0c; 一般意义上是指只有纯黑&#xff08;0&#xff09;、纯白&#xff08;255&#xff09;两种颜色的图像…

4、im2bw 和 imbinarize 的区别与图像分割的综合应用

1. im2bw 和 imbinarize 的区别 将图片转换为二值图有两个函数&#xff0c;分别为&#xff1a; bw imbinarize(g); 与 bw im2bw(g);在 matlab2018 中建议用 imbinarize 来将图片转换为二值图&#xff0c;其参数必须为灰度图。 在 matlab2016 中&#xff0c;只有 im2bw 函…

理解Kalman滤波的使用

Kalman滤波简介 Kalman滤波是一种线性滤波与预测方法&#xff0c;原文为&#xff1a;A New Approach to Linear Filtering and Prediction Problems。文章推导很复杂&#xff0c;看了一半就看不下去了&#xff0c;既然不能透彻理解其原理&#xff0c;但总可以通过实验来理解其具…

卡尔曼滤波(Kalman Filtering)——(6)MATLAB仿真(保姆级)

MATLAB仿真 一、卡尔曼滤波的实际应用二、流程图三、执行过程四、程序代码五、仿真结果参考文献 一、卡尔曼滤波的实际应用 在这里依旧以前面提到的测量硬币为例进行MATLAB仿真。现有一枚硬币为了这枚硬币的直径&#xff0c;我们进行了多次测量&#xff0c;但是所使用的的尺子存…

Kalman Filter 遇到 Deep Learning : 卡尔曼滤波和深度学习有关的论文

突然心血来潮&#xff0c;想到卡尔曼滤波器是否能和深度学习结合。于是从谷歌学术上搜了一下&#xff0c;发现现在这方面的工作还没有太多结合。Top 期刊 TNNLS 2021 有一篇最新工作。ICLR 2020 出现一篇 Kalman Filter Is All You Need 的文章&#xff0c;但目前从开源的审稿意…

目标跟踪:卡尔曼滤波(Kalman Filter)到底是怎么工作的?

Kalman filter到底是怎么工作的&#xff1f; 本文主要参考的文章&#xff1a;https://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/&#xff0c;图片也基本来自上述博客 其实接触KF已经很久了&#xff0c;听过对应的课程&#xff0c;也对着公式进行过推导&#x…