Linux进阶·如何在Ubuntu安装、调试、运行gcc/g++,以及如何进行多文件编译

news/2024/12/14 11:48:04/

目录

1.  简介

gcc-toc" style="margin-left:0px;">2.  安装gcc

gcc%E7%9A%84%E7%BC%96%E8%AF%91%E6%B5%81%E7%A8%8B-toc" style="margin-left:0px;">3.  gcc的编译流程

3.1  预处理

 3.2  编译

3.3  汇编

3.4  链接

gcc%E7%9B%B8%E5%85%B3%E5%8F%82%E6%95%B0-toc" style="margin-left:0px;">4.  gcc相关参数

5.  多文件编译

gcc%E5%92%8Cg%2B%2B%E7%9A%84%E5%8C%BA%E5%88%AB-toc" style="margin-left:0px;">6.  gcc和g++的区别


1.  简介

        gcc是Linux下的编译工具集,是GNU Compiler Collection的缩写,包含gcc, g++等编译器。这个工具集不仅包含编译器,还包含其他工具集,例如ar,nm等。

        gcc是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++和Objective-C等语言编写的程序。gcc又是一个交叉平台编译器,它能够在当前CPU平台上为多种不同体系结构的硬件平台开发软件,因此尤其适合嵌入式领域的开发编译。

        对于gcc支持的编译源文件的后缀名及其解释如下:

后缀名所对应的语言
.cC源程序
.C/.cc/.cxxC++源程序
.mObjective-C源程序
.i经过预处理的C源程序
.ii经过预处理的C++源程序
.s/.S汇编语言源程序
.h预处理文件(头文件)

.o

目标文件
.a/.so编译后的库文件

gcc">2.  安装gcc

        有些纯净版的 Linux 默认没有 gcc 编译器,需要自己安装,如果你不知道自己有没有安装gcc,可以输入一下命令进行查看:

//查看 gcc 的版本
gcc -v
//或者
gcc --version//查看 g++ 的版本
g++ -v
//或者
g++ --version

        使用gcc -v查看如下: 

        下滑可以看到gcc当前的版本: 

        使用gcc --version可以看到,其显示的信息是比较少的,但版本信号是一样的:

        使用g++ -v查看:

        同样下滑可以看到当前版本:

        使用g++ --version:

        若是显示不是上面的,或者找不到gcc......,安装步骤如下:

//需要管理权限
//bubutu上面安装
sudo apt update //更新本地的软件下载列别列表,得到最新的下载地址sudo apt install gcc g++ //通过下载列表提供的地址下载安装包,并安装//centos上面安装
sudo yum updatesudo yum install gcc g++

        下面演示Ubuntu上下载:

gcc%E7%9A%84%E7%BC%96%E8%AF%91%E6%B5%81%E7%A8%8B">3.  gcc的编译流程

        gcc的编译流程可分为四个阶段:预编译(预处理)→ 编译和优化 → 汇编 → 链接。

文件名后缀说明gcc参数
.c源文件
.i预处理后的C文件-E
.s编译后得到的汇编语言的源文件-S
.o汇编后得到的二进制文件-c

3.1  预处理

        编译器将*.c代码的头文件编译进来,例如我们头文件声明的是:include<stdio.h>那么就会将stdio.h编译进来,用户可以使用gcc的选项“-E”进行查看,该选项的作用是让gcc在预处理结束后停止编译过程。

        该阶段主要进行三件事:展开头文件、宏替换、去掉注释行。

        演示一下,首先我们先创建一个.c的文件:

        其中.c文件内容为:

         这里对于Linux的一些基础命令和vi/vim编辑器的使用不做过多的描述,想要详细了解的可以看:

Linux常用命令详细解析(含完整命令演示过程)-CSDN博客

Linux命令进阶·vi\vim编辑器详细命令介绍-CSDN博客

        主要演示gcc的过程:

        对于一下这条命令进行解读:

gcc -E hello.c -o hello.i
  • gcc: 是 GCC 编译器的命令,通常用于编译 C 语言程序。
  • -E: 这个选项告诉 GCC 只进行预处理,而不进行编译、汇编或链接。预处理包括宏替换、文件包含和条件编译等。
  • hello.c: 这是你输入的源代码文件,通常是 C 语言源代码文件。
  • -o hello.i: 该选项指定输出文件的名称。在这里,预处理的结果会被保存到 hello.i 文件中,.i 是预处理后的 C 代码文件扩展名。
     

        我们可以通过cat命令查看文件内容,首先是.c文件:

        对.i文件进行查看,可以看到头文件被展开了:

        往下翻可以看到,对比.c文件黄色部分的注释被清除了,蓝色部分3的位置开始时NUMBER的宏定义,此时被替换成3:

        我们也可以直接通过vim hello.i进行查看:

 3.2  编译

        在编译阶段,gcc首先要检查代码的规范性,以及收否有语法错误等,以确定代码是否能正常工作,无误后,gcc把代码翻译成汇编语言,用户可以使用“-S”选项进行查看,该选项只是进行编译而不进行汇编,最终生成一个汇编代码。

  • gcc: 是 GCC 编译器的命令。
  • -S: 这个选项告诉 GCC 执行到汇编阶段。它会把源代码编译成汇编语言代码,而不是生成机器码或可执行文件。
  • hello.i: 这是输入文件,应该是一个已经经过预处理的 C 语言源代码文件(通常是 .i 文件)。
  • -o hello.s: 这个选项指定输出文件的名称。这里的 hello.s 文件将包含生成的汇编代码。
     

        同样的,我们可以查看此时.s文件的内容:

3.3  汇编

        该阶段吧编译阶段生成的.s文件转换成目标文件,用户可以使用-c选项查看,汇编代码转换成后缀名为.o的二进制目标代码。

        查看一下,可以发现都是一些二进制文件,不过这里识别不出来,因此显示的是乱码:

3.4  链接

        编译成功后,就进入了链接阶段。

        函数库一般分为静态库和动态库两种:静态库在编译链接时,把库文件的代码全部加入可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了,其后缀名一般为".a”。动态库与之相反,在编译链接时并没有把库文件的代码加入可执行文件中,而是在程序执行时链接文件加载库,这样可以节省系统的开销,动态库的后缀名一般为“.so”。 gcc在编译时默认使用动态库。

        可以看到生成一个可自行程序 hello,点击运行看看:

        到这里一个程序就算运行完成,不过我们会发现,这个步骤太繁琐,实际上我们要执行程序不需要那么繁琐的步骤,上面只是为了演示其运行流程,实际我们可以直接使用:

gcc hello.c -o hello2(生成的链接名自己定义)

        或者我们可以直接省略-o:

        可以看到生成了一个a.out的链接,这是因为如果我们不指定生成的链接名。其会默认给出一个a.out的链接名。

gcc%E7%9B%B8%E5%85%B3%E5%8F%82%E6%95%B0">4.  gcc相关参数

参数名称含义
-c只编译不链接成为可执行文件(生成后缀为 .o 的文件)
-S只编译不汇编和链接(生成后缀为 .s 的预编译文件)
-E仅执行预处理,不进行编译、汇编和链接(生成后缀为 .i 的预编译文件)
-o [file1] [file2]/[file2] -o [file1]将文件file2编程file1
-I dir(这里是大写的i)指定include包含文件的搜索目录
-L dir在库文件的搜索路径列表中添加dir目录
-l lib(这里是小写的L)指定程序要链接的库,lib为库文件名称。
-g生成调试信息,方便gdb调试
-D define预定义宏
-w不输出任何警告信息
-Wall开启编译器的所有警告选项
-static链接静态库生成目标文件,禁止使用动态库(在支持动态链接的系统上)
-share尽量使用动态库,但前提是系统存在动态库,生成的目标文件较小
-shared生成共享文件,然后可以与其它文件链接生成可执行文件
-fpic生成适用于共享库的与地址无关的代码(PIC)(如果机器支持的话)
-fPIC生成与位置无关的的代码,适用于使用动态库,与“-fpic”的区别在于去除去全局偏移表的任何限制(如果机器支持的话)
-fPIE使用与地址无关的代码生成可执行文件

5.  多文件编译

        首先我们随便找个地方存放以下文件,这里我将test文件里面的内容删除了,重新放入的:

        每个文件的内容为:

        以上那么多.c文件,若是我们要一个个链接太过繁琐:

        有一种简单的写法,可以使用通配符:

        可以看到生成了一个a.out的链接,运行可得:

gcc%E5%92%8Cg%2B%2B%E7%9A%84%E5%8C%BA%E5%88%AB">6.  gcc和g++的区别

6.1  在代码编译阶段

后缀为.c 的文件:

        gcc 把它当作是 C 代码来编译。

        g++ 也会将 .c 文件当作 C 代码来编译,但它会默认启用 C++ 编译器的一些特性,例如自动定义 _cplusplus 宏等。因此,g++ 处理 .c 文件时实际上会使用 C++ 编译器进行编译,但不影响文件本身。

后缀为.cpp 的文件:

        gcc 和 g++ 都会将 .cpp 文件当作 C++ 代码来编译。尽管 gcc 可以编译 C++ 代码,但它默认使用 C 编译器进行处理,可能需要手动指定编译器选项(如 -std=c++11)来正确处理 C++ 语法。

        g++ 会使用 C++ 编译器,并且会自动处理 C++ 相关的特性,例如 C++ 的名称修饰(name mangling)、模板、异常处理等。

g++ 会自动启用 C++ 编译选项,而 gcc 默认用于 C 编译。

6.2  在链接阶段

        gcc 和g++都可以自动链接到标准C库

        g++ 会自动链接 C++ 标准库 (libstdc++),而 gcc 则不会自动链接 C++ 标准库。如果你使用 gcc 编译 C++ 程序,必须显式指定链接 C++ 标准库(例如:gcc -lstdc++)。

举个例子:

        我们创建一个.cpp文件,内容为:

         直接使用 g++ 来编译和链接这个 C++ 文件:

g++ example.cpp -o example

        g++ 会自动选择 C++ 编译器,并且在链接时自动链接 C++ 标准库(libstdc++)。因此,无需手动指定链接库,g++ 会负责这些操作。最终会生成一个可执行文件 exanple,你可以直接运行它: 

         使用 gcc 来编译和链接同一个 C++ 程序,你需要手动告诉编译器链接 C++ 标准库,因为 gcc 默认只链接 C 标准库(libc),而不会自动链接 C++ 标准库:

        进行手动连接:

gcc example.cpp -o example -lstdc++

6.3  关于_cplusplus 宏的定义

        g++ 会自动定义_cplusplus 宏,这是一个用于标识 C++ 编译器的标准宏,这个不影响它去编译 C程序。

        gcc 会根据源文件的类型来判断是否定义 _cplusplus 宏。如果编译的是 C 文件(.c 后缀),则不会定义 _cplusplus 宏;如果是 C++ 文件(.cpp 后缀),则会定义它。

Linux常用命令详细解析(含完整命令演示过程)_linux命令实例详解-CSDN博客

Linux命令进阶·vi\vim编辑器详细命令介绍-CSDN博客

Linux学习_时光の尘的博客-CSDN博客


http://www.ppmy.cn/news/1555006.html

相关文章

测试线上问题复盘文档

一、错误简述 问题发生的时间线及行为 二、错误影响 影响范围 三、根本原因分析 刨根问底&#xff0c;顺藤摸瓜&#xff0c;造成错误的最根本原因是什么 四、反省经验 吃一堑长一智&#xff0c;从错误中学习到的宝贵经验 五、纠正措施 为了避免重蹈覆辙&#xff0c;都有那些短期…

更新数据时Redis的操作

一般做法是在数据库更新后删除Redis中对应的缓存数据&#xff0c;而非更新数据。那么为什么要这么做呢&#xff1f; 以下是一些拙见 场景使用 金融交易系统&#xff1a;在金融领域&#xff0c;数据的准确性至关重要。任何数据不一致都可能导致严重的财务损失。因此&#xff0…

题目 2780: 奇偶数判断

题目 2780: 奇偶数判断 时间限制: 2s 内存限制: 192MB 提交: 11198 解决: 6848 题目描述 给定一个整数&#xff0c;判断该数是奇数还是偶数。 输入格式 输入仅一行&#xff0c;一个大于零的正整数n。 输出格式 输出仅一行&#xff0c;如果n是奇数&#xff0c;输出odd&#xff1…

Django 与 Flask 框架深度剖析

一、框架概述 起源与发展 Django&#xff1a; 诞生于新闻应用开发环境&#xff0c;旨在快速构建复杂、数据库驱动的网站。由 Django 软件基金会维护&#xff0c;拥有庞大的社区支持&#xff0c;持续更新迭代。其发展遵循稳定、功能丰富的路线&#xff0c;注重安全性与可扩展性的…

全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之计数器与累加器实战题目

题目1—三个连续的自然数计算 问题描述&#xff1a; 若有3个连续的自然数&#xff0c;已知第一个自然数为100&#xff0c;请编写程序输出这3个自然数。 输入格式&#xff1a; 无 输出格式&#xff1a; 三行三个整数 输入输出样例&#xff1a; 输入样例 输出样例 无 1…

Tongweb7049M4有关SSL/TLS 服务器瞬时 Diffie-Hellman 公共密钥过弱的处理方案(by lqw)

前提条件&#xff1a;Tongweb7049M4已在http通道里配置了https&#xff08;如何配置https可以参考这个帖子&#xff1a;东方通TongWEB添加Https证书&#xff0c;开启SSL&#xff09; 遇到客户在配置了https后&#xff0c;扫描漏洞提示&#xff1a; 有关SSL/TLS 服务器瞬时 Dif…

电子电气架构 --- 智能座舱域控制器及座舱芯片(SoC)

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…

隐私保护新动态:Facebook近期政策更新的核心要点

随着全球用户对隐私保护意识的增强&#xff0c;Facebook作为全球最具影响力的社交媒体平台之一&#xff0c;也加快了在隐私政策上的革新步伐。这次的隐私政策更新不仅在透明度上有了长足进步&#xff0c;也更全面地保护了用户的数据安全。接下来&#xff0c;我们将多维度地解析…