Linux GCC 编译详解

news2024/9/22 11:27:41

文章目录

    • 一、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 DEBUG
    printf("hello itcast\n");
#endif
    printf("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://www.coloradmin.cn/o/392935.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tomcat安装步骤及详细配置教程

Tomcat安装及配置教程主要分为四步&#xff1a; 步骤一&#xff1a;首先确认自己是否已经安装JDK 步骤二&#xff1a;下载安装Tomcat 步骤三&#xff1a;Tomcat配置环境变量 步骤四&#xff1a;验证Tomcat配置是否成功 一、首先确认自己是否已经安装JDK WinR打开运行&…

sklearn手册(持续更新ing...)

诸神缄默不语-个人CSDN博文目录 本文是一个随时使用sklearn时可供参考的手册。我有使用sklearn的基础&#xff0c;且准备后期直接用sklearn官方的教程文档参考撰写系统性学习sklearn包使用方法的sklearn用户教程一文&#xff0c;因此本文就不介绍基础了。 最近更新时间&#…

ubuntu 20.04 Linux下查看当前文件夹的大小

问题描述 由于使用远程的 ssh 连接 ubuntu 20.04&#xff0c;所以不清楚如何查看 当前文件夹的大小 直接使用 df -h&#xff0c;只能查看 当前系统 磁盘的使用情况 需求 通过Linux shell 命令行&#xff0c;查看 当前文件夹占用的大小 其实很简单&#xff0c;使用 Linux sh…

如何使用码匠连接 Oracle

目录 在码匠中集成 Oracle 在码匠中使用 Oracle 关于码匠 Oracle 是一种关系型数据库&#xff0c;可用于存储和管理大量结构化数据。Oracle 数据源支持多种操作系统&#xff0c;包括 Windows、Linux 和 Unix 等&#xff0c;同时也提供了各种工具和服务&#xff0c;例如 Orac…

从设计转到了产品,实习生工作复盘

一、写在前面从设计转到了产品&#xff0c;产品的门槛好像相对于设计确实要低一些。通过产品新人必读书《人人都是产品经理》、知乎产品大神的观点和我个人的理解&#xff0c;可以得出一个结论——并不是每个人都是合格的产品经理&#xff0c;包括我在内的很多人都是因为公司有…

​2023年湖北武汉自己怎么报考二建?报考二建学历不符怎么办?启程别

2023年湖北武汉自己怎么报考二建&#xff1f;报考二建学历不符怎么办&#xff1f;启程别 2023年武汉自己怎么报考二建&#xff0c;首先个人是没有办法报名的&#xff0c;报考二建必须以企业的名义报名。报考二建的基本条件是什么&#xff1f;启程别告诉你&#xff0c;“启程别”…

Spark AQE

Spark AQEAQE/RBO/CBOAQEAQE特点Join 策略调整自动分区合并自动倾斜处理Spark 3.0 添加了自适应查询执行&#xff08;AQE&#xff09;、动态分区剪裁&#xff08;DPP&#xff09;、扩展的 Join Hints AQE/RBO/CBO Spark SQL 2.0前&#xff0c;仅支持启发式、静态的优化过程。…

mybatis面试题 一

一、MyBatis工作原理&#xff1f; 1、 创建SqlSessionFactory 2、 通过SqlSessionFactory创建SqlSession 3、 通过sqlsession执行数据库操作 4、 调用session.commit()提交事务 5、 调用session.close()关闭会话 1&#xff09;读取 MyBatis 配置文件&#xff1a;mybatis-c…

zynq7000系列芯片介绍

ZYNQ从架构上可以划分为两大模块&#xff0c;一个是PS&#xff08;处理器系统&#xff09;&#xff0c;另一个是PL&#xff08;可编程逻辑&#xff09; PS由APU、内存接口、IO外设、互连线4大模块组成。 1、APU&#xff08;Application Processor Unit)应用处理单元 即PS【可编…

面向对象设计模式:行为型模式之状态模式

文章目录一、引入二、状态模式2.1 Intent 意图2.2 Applicability 适用性2.3 类图2.4 Collaborations 合作2.5 Implementation 实现2.5 状态模式与策略模式的对比2.5 状态模式实例&#xff1a;糖果机2.6 状态模式实例&#xff1a;自行车升降档一、引入 State Diagram 状态图&am…

docker数据卷及软件部署方式

目录 一、docker数据卷管理 1.docker数据卷概念 2.数据卷命令 3.创建容器并挂载数据卷 二、docker软件部署 1.docker部署mysql方式 下载MySQL5.7镜像文件 创建所需的数据卷目录 创建mysql容器并挂载数据卷 进入数据库授权远程连接用户访问 2. docker部署nginx方式 下…

C语言-基础了解-16-C字符串

C字符串 一、C字符串 在 C 语言中&#xff0c;字符串实际上是使用空字符 \0 结尾的一维字符数组。因此&#xff0c;\0 是用于标记字符串的结束。 空字符&#xff08;Null character&#xff09;又称结束符&#xff0c;缩写 NUL&#xff0c;是一个数值为 0 的控制字符&#x…

剑指 Offer 31. 栈的压入、弹出序列

一、题目描述 输入两个整数序列&#xff0c;第一个序列表示栈的压入顺序&#xff0c;请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。 例如&#xff0c;序列 {1,2,3,4,5} 是某栈的压栈序列&#xff0c;序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列…

centos7 安装 hyperf

​​​​​​PHP > 7.4 Swoole PHP 扩展 > 4.5&#xff0c;并关闭了 Short Name OpenSSL PHP 扩展 JSON PHP 扩展 PDO PHP 扩展 Redis PHP 扩展 Protobuf PHP 扩展 composer create-project hyperf/hyperf-skeleton 推荐安装项 全部选n php.ini [swoole] extens…

LQB小板焊接V3版本的小板原理图,PCB图,注意事项和步骤

第一部分&#xff0c;这个部分&#xff0c;可以不焊接&#xff0c;直接用买的下载器进行下载代码&#xff0c;外接一个下载器&#xff0c;网上大概是10元左右&#xff0c;以后学习stm32的芯片的时候&#xff0c;这个下载器就是一个串口转换器&#xff0c;也可以使用。。 当然也…

realloc也可以缩容了??

作者&#xff1a;小树苗渴望变成参天大树 作者宣言&#xff1a;认真写好每一篇博客 作者gitee:gitee 如 果 你 喜 欢 作 者 的 文 章 &#xff0c;就 给 作 者 点 点 关 注 吧&#xff01; realloc的细节前言一、realloc的原地扩容和异地扩容二、关于realloc是否可以缩容问题前…

快速搭建本地服务器

一、anywhere 1、npm install anywhere -g 2、打开位于文件夹下的终端页&#xff0c;输入anywhere 9999 9999这里是设置端口号&#xff0c;端口号自行设置&#xff0c;也可以不输入xxx会默认8080端口号 二、http-server 1、npm install http-server -g 2、打开位于文件夹下…

[golang]Go语言从入门到实践-反射

反射三定律&#xff1a; 1.变量---->反射变量 2.变量---->反射变量---->接口 3.变量----->(通过取地址&)反射变量---->修改变量的值 反射的类型和种类&#xff1a; 切片、集合、结构体、指针、函数与反射...... 总结&#xff1a; 内置包函数 reflect 的…

darknet测试yolo

原文链接&#xff1a;https://wangguo.site/posts/38432.html YOLO: Real-Time Object Detection 1、下载yolo权重文件 mkdir model #新建文件夹放权重文件 cd model wget https://pjreddie.com/media/files/yolov3.weights2、测试图片 执行命令 ./darknet detect cfg/yolo…

(socket编程实验中遇到的问题)connect error no route to host

在编写网络编程的时候遇到了这个问题connect error no route to host socket编程&#xff08;服务端与客户端&#xff09; 上网一搜全是&#xff1a; 两台机器进行socket通信时&#xff0c;可能在连接时出现错误&#xff1a; connect error: No route to host(errno:113) 出…