linux环境下C程序的编译过程以及makefile的简单使用

        在windows下,很多用来进行编程软件对于写好的文件,点击编译即可生成想要文件。如.exe可执行文件,.hex文件或者.bin文件等等。软件为我们省略了很多事。但是对于linux初学者来说,初次接触linux系统,面对命令行黑框框有点无从下手,也不明白linux下C程序不用可视化编译器如何对程序进行编译,生成可执行文件。

一、C文件的编译过程 

        C语言的编译过程是将源代码转换成计算机能够被理解的机器代码的过程。一般来说主要为以下流程。

C文件->预处理->编译->汇编->连接->可执行文件。

1.1预处理

        首先是预处理阶段,主要对源代码的预处理指令进行处理,如头文件 #include <stdio.h>、宏定义 #define  XX 等等。将#include <xx.h>替换成头文件中的东西,并删除不属于程序的内容,如程序中的注释。预处理完输出的文件被称为pp文件,通常以.i或者.ii结尾。

1.2编译

        编译阶段,通过编译器将预处理后的文件转换为汇编语言代码。在这个过程中,编译器会进行词法分析和语法分析,检查代码的语法和语义,确保代码的正确性。同时,编译器还会生成与平台相关的汇编代码。编译阶段完成后,会生成一个或多个汇编文件,这些文件是用汇编语言编写的,包含了与C语言源代码对应的机器代码指令。

1.3汇编

        汇编阶段,将编译阶段生成的汇编码转换为目标文件,汇编器将汇编代码转换为机器码,并生成一个或者多个目标文件.o或.obj文件。

1.4链接

        链接过程是将汇编阶段生成的目标文件或者多个目标文件以及库文件合并成一个可执行文件。链接器还会进行地址解析和重定位等工作,以确保最终生成的可执行文件中的地址正确无误。链接阶段完成后,会生成最终的可执行文件,这个文件可以直接在操作系统上运行。

二、GCC编译器

        gcc编译器是linux环境中使用的比较多的一个编译器,gcc(GNU Compiler Collection,GNU编译器套件)。

        在linux下可以直接通过命令行查看gcc编译器的使用方法

man gcc

        在命令行界面中直接输入man gcc即可查看使用方法

gcc         xx1        xx2

xx1为选项,即使用gcc进行什么操作 xx1可为以下几种选项

 -c: 只编译不链接为可执行文件,编译器将输入的.c 文件编译为.o 的目标文件。


 -o: <输出文件名>用来指定编译结束以后的输出文件名,如果不使用这个选项的话 GCC 默
认编译出来的可执行文件名字为 a.out。 例 gcc -o hello hello.c  hello为生成的可执行文件的名字,hello.c为需要编译的c文件。


 -g: 添加调试信息,如果要使用调试工具(如 GDB)的话就必须加入此选项,此选项指示编
译的时候生成调试所需的符号信息。


 -O: 对程序进行优化编译,如果使用此选项的话整个源代码在编译、链接的的时候都会进
行优化,这样产生的可执行文件执行效率就高。


-O2: 比-O 更幅度更大的优化,生成的可执行效率更高,但是整个编译过程会很慢。

2.1 编译流程

       GCC 编译器的编译流程是:预处理、编译、汇编和链接。预处理就是展开所有的头文件、
替换程序中的宏、解析条件编译并添加到文件中。编译是将经过预编译处理的代码编译成汇编
代码,也就是我们常说的程序编译。汇编就是将汇编语言文件编译成二进制目标文件。链接就
是将汇编出来的多个二进制目标文件链接在一起,形成最终的可执行文件,链接的时候还会涉
及到静态库和动态库等问题。

2.2 单个文件编译运行

      对于简单的单个的C程序,只需要调用系统的头文件,而不需要调用外部自己编写的c程序,那么只需要使用 gcc -o  xx   xx.c即可。如下所示。

在命令行中输入

vi hello.c

在hello.c中添加一个简单的c程序

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

保存后退出,使用gcc编译

gcc -o hello hello.c

使用ls 即可查看到生成的hello文件

        

运行 ./hello  即可看到命令行输出打印信息

2.3 多个文件编译链接运行

        通过键盘输入两个整形数字,然后计算他们的和并将结果显示在屏幕上,在这个工程中我们有 main.c、 input.c 和 calcu.c 这三个 C 文件和 input.h、 calcu.h 这两个头文件。其中 main.c 是主体, input.c 负责接收从键盘输入的数值, calcu.c 进行任意两个数相加。

在文件夹中创建以下几个文件

 main.c

  1 #include <stdio.h>
  2 #include "input.h"
  3 #include "calcu.h"
  4 
  5 int main(int argc, char *argv[])
  6 {
  7  int a, b, num;
  8  input_int(&a, &b);
  9  num = calcu(a, b);
 10  printf("%d + %d = %d\r\n", a, b, num);
 11  }

input.c

#include <stdio.h>
#include "input.h"

void input_int(int *a, int *b)
 {
  printf("input two num:");
  scanf("%d %d", a, b);
  printf("\r\n");
 }

calcu.c

#include "calcu.h"
int calcu(int a, int b)
{
  return (a + b);
}

input.h

#ifndef _INPUT_H
#define _INPUT_H

void input_int(int *a, int *b);

#endif

calcu.h

#ifndef _CALCU_H
#define _CALCU_H

int calcu(int a, int b);

#endif

输入命令行 

gcc main.c calcu.c input.c -o main

对 main.c calcu.c input.c 进行编译并链接成 main 可执行文件

运行结果

三、 makefile引入使用

3.1 实例

对于2.3中的例子,只需要一行代码即可解决编译,看起来还是挺简单的。但是在实际项目中,有很多.c和.h文件,如果每次都这样编译链接的话可就太麻烦了。因此引入makefile简化这个编译流程。

在当前文件中创建一个 Makefile文件

vi Makefile

在代码中添加

  1 main: main.o input.o calcu.o
  2         gcc -o main main.o input.o calcu.o
  3 main.o: main.c
  4         gcc -c main.c
  5 input.o: input.c
  6         gcc -c input.c
  7 calcu.o: calcu.c
  8         gcc -c calcu.c
  9 
 10 clean:
 11         rm *.o
 12         rm main

写好makefile后,使用make 即可对多个文件进行编译、链接

make

可以看到编译器单独对 main.c input.c calcu.c 进行了编译,最后链接生成了main.o可执行文件

对于多个C文件来说,方便了很多。

3.2 makefile解释

  1 main: main.o input.o calcu.o
  2         gcc -o main main.o input.o calcu.o
  3 main.o: main.c
  4         gcc -c main.c
  5 input.o: input.c
  6         gcc -c input.c
  7 calcu.o: calcu.c
  8         gcc -c calcu.c
  9 
 10 clean:
 11         rm *.o
 12         rm main
   main: main.o input.o calcu.o
           gcc -o main main.o input.o calcu.o

        main 是最后需要生成的目标文件,而main.o input.o calcu.o是生成main所需要的依赖文件
如果要更新目标 main,就必须先更新它的所有依赖文件,如果依赖文件中的任何一个有更新,那么目标也必须更新,“更新”就是执行一遍规则中的命令列表。 并通过gcc 命令将main.o input.o calcu.o链接成可执行文件main。

   main.o: main.c
           gcc -c main.c

如上述代码差不多,main.o为目标文件,main.c为依赖文件,通过执行gcc -c main.c生成目标文件。input.o calcu.o跟这个一样就不过多阐述了。

  clean:
          rm *.o
          rm main

        当需要清除生成的目标文件时,可通过命令行控制,删除以.o结尾的目标文件 ,删除可执行文件 main。

可以看到,输入make clean命令后,以上文件皆被删除了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/895469.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java后端面试题:MySQL篇

目录 MySQL基础部分 1. SELECT语句完整的执行顺序是什么&#xff1f; 2. 说一说内连接和外连接。 3. 请说说数据库三大范式。 4. 请你说说视图的作用&#xff0c;视图可以更改么&#xff1f; 架构 5. 请你说一说MySQL架构。 6. 请你说说一条SQL语句的执行过程&#xff…

MIT 6.5840(6.824) Lab 5:Sharded Key/Value Service 设计实现

文章目录 1 实验要求1.1 介绍1.2 lab5A&#xff1a;控制器和静态分片1.3 lab5B&#xff1a;碎片移动1.4 挑战任务 2 实验设计2.1 整体架构2.2 shardctrler2.3 shardkv server2.3.1 结构2.3.2 日志类型2.3.3 读写服务2.3.4 配置更新检测2.3.5 分片迁移2.3.6 垃圾回收2.3.7 空日志…

一个简单的Qt Console Application计算练习程序

初步体验Qt Creator 用途&#xff1a;练习20以内2位数乘法速算的程序 功能1&#xff1a;支持用户设定题目数量 std::cout << "请输入本次练习题目数量&#xff1a;";int numProblems 0;std::string num;std::cin >> num;try {numProblems std::stoi(…

【云从】六、云存储

文章目录 1、应用架构2、存储设备3、存储方案3.1 直连式存储DAS3.2 网络连接存储NAS3.3 存储区域网络SAN3.4 分布式存储ServerSAN3.5 软件定义存储SDS 4、云存储4.1 云硬盘CBS4.2 文件存储CFS4.3 对象存储COS 1、应用架构 2、存储设备 硬盘性能对比&#xff1a; 硬盘接口对比&…

ubuntu docker安装elasticsearch:7.12.1

#es和kibana容器互联网络 docker network create es-netdocker pull elasticsearch:7.12.1 docker pull kibana:7.12.1 mkdir -p /root/datas/docker/es/data mkdir -p /root/datas/docker/es/logs mkdir -p /root/datas/docker/es/pluginssudo chmod -R 777 /root/datas/docke…

高级算法设计与分析 学习笔记13 线性规划

注意是线性规划不是动态规划哦 好家伙&#xff0c;这不是凸优化吗&#xff1f; 凸优化标准形式&#xff1a; 先改成统一最大化&#xff08;凸优化那边怎么是统一最小化&#xff1f;&#xff09; 原来的x2正负无所谓&#xff0c;但我希望每个x都是有限制的&#xff0c;所以把它改…

鸿蒙网络编程系列24-Web组件与应用互操作示例

1. APP内嵌网页与应用互操作概述 在通常的APP开发中&#xff0c;经常会采用内嵌网页的形式&#xff0c;通过网页来展现丰富的动态内容&#xff0c;虽少了很多原生开发的功能&#xff0c;但是这么做无可厚非&#xff0c;毕竟APP需要适配的系统平台很多&#xff0c;比如安卓、苹…

递归神经网络(RNN)简介

递归神经网络简介 在本文中,我们将介绍神经网络的一种新的变体,即递归神经网络,也称为 (RNN),当数据是连续的时,如时间序列数据和文本数据,它比简单的神经网络效果更好。 什么是递归神经网络 (RNN)? 循环神经网络 (RNN) 是一种神经网络,其中上一步的输出作为当前…

王道考研视频——操作系统笔记

操作系统 1.1 操作系统的概念、特征、功能、目标 操作系统&#xff08; Operating System&#xff0c;OS&#xff09;是指控制和管理整个计算机系统的硬件和软件资源&#xff0c;并合理地组织调度计算机的工作和资源的分配&#xff0c;以提供给用户和其他软件方便的接口和环境…

[数据结构]栈的实现与应用

文章目录 一、引言二、栈的基本概念1、栈是什么2、栈的实现方式对比3、函数栈帧 三、栈的实现1、结构体定义2、初始化3、销毁4、显示5、数据操作 四、分析栈1、优点2、缺点 五、总结1、练习题2、源代码 一、引言 栈&#xff0c;作为一种基础且重要的数据结构&#xff0c;在计算…

【数据结构】滑动窗口算法详解:高效解决子串问题

滑动窗口&#xff08;Sliding Window&#xff09;是一种常用于处理数组或字符串中子序列问题的算法技巧。它通过维护一个窗口来限制待处理的数据范围&#xff0c;从而高效地解决问题&#xff0c;避免重复计算。它的时间复杂度通常为 O(N)&#xff0c;相较于暴力破解&#xff08…

Go 项目如何集成类似mybatisPlus插件呢?GORM走起!!

导读&#xff1a; 在 Go 项目中&#xff0c;虽然没有像 MyBatis Plus 这样特定的 ORM 插件&#xff0c;但可以使用功能相似的 Go ORM 框架&#xff0c;比如 GORM&#xff0c;它支持链式查询、自动迁移、预加载等功能&#xff0c;与 MyBatis Plus 有相似之处。通过一些插件或扩…

常用API

Object类&#xff1a; instanceof&#xff1a;java中的关键字&#xff0c;判断左边的对象是否是右面类的实例。 它的作用是判断其左边对象是否为其右边类的实例&#xff0c;返回boolean类型的数据。 getClass()&#xff1a;得到调用者的数据类型&#xff1b; 进行对象内容比较…

016_基于python+django网络爬虫及数据分析可视化系统2024_kyz52ks2

目录 系统展示 开发背景 代码实现 项目案例 获取源码 博主介绍&#xff1a;CodeMentor毕业设计领航者、全网关注者30W群落&#xff0c;InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者&#xff0c;博客领航之星、开发者头条/腾讯云/AW…

盘点现代浏览器的各种神奇能力,功能令人惊讶

盘点现代浏览器的各种神奇能力&#xff0c;功能令人惊讶&#x1f62e; 浏览器的进化 一个运行在浏览器里面的操作系统。一个炫酷的量子纠缠网页。内嵌在浏览器里面的AI大模型。 随着web技术的迅猛发展&#xff0c;现代浏览器已经不仅仅是一个浏览网页的工具了。它的功能早已进…

【判断推理】逻辑论证之归因论证

2.1 归因论证概述 归因&#xff1a;指人们对 他人或自己行为的原因的推论过程。具体而言&#xff0c;就是观察者对他人的行为过程或自己的行为过程所进行的因果解释和推论。&#xff08;通俗而言&#xff0c;归因就是对已经发生的事实&#xff0c;在众多可能的原因中找出一个原…

Cesium 实战 - 自定义纹理材质 - 立体墙(旋转材质)

Cesium 实战 - 自定义纹理材质 - 立体墙(旋转材质) 核心代码完整代码在线示例Cesium 给实体对象(Entity)提供了很多实用的样式,基本满足普通项目需求; 但是作为 WebGL 引擎,肯定不够丰富,尤其是动态效果样式。 对于实体对象(Entity),可以通过自定义材质,实现各种…

CLion和Qt 联合开发环境配置教程(Windows和Linux版)

需要安装的工具CLion 和Qt CLion下载链接 :https://www.jetbrains.com.cn/clion/ 这个软件属于直接默认安装就行&#xff0c;很简单&#xff0c;不多做介绍了 Qt:https://mirrors.tuna.tsinghua.edu.cn/qt/official_releases/online_installers/ window 直接点exe Linux 先c…

【2024软著申请】软著申请到发放全流程(附带教程+工具+撰写建议)

目录 总时间线材料准备1、计算机软件著作权登记申请表4页2、身份证明文件3、软件鉴别材料4、文档鉴别材料 唠叨两句 总时间线 时间关键节点20240811电子材料提交进入待受理阶段20240826受理阶段审查通过&#xff0c;进入审查中20240930发放完成 材料准备 版权登记链接(https…

用柔性神经k-Opt学习搜索路径问题的可行和不可行区域(未完,先看前驱文章L2S)

文章目录 Abstract1 IntroductionAbstract 介绍了一种名为 Neural k-Opt(NeuOpt)的新型学习搜索(L2S)求解器,用于解决路径问题。它学习执行基于定制的动作分解方法和定制的循环双流(Recurrent Dual-Stream)解码器的灵活 k-opt 交换。 作为一项开创性的工作,我们绕过了…