『Linux - gcc / g++』c程序翻译过程

news2024/10/5 13:58:30

文章目录

  • 前言
    • 预处理 -E
    • 编译 -S
    • 汇编 -c
    • 链接
      • 动静态链接

前言

在计算机中的每一个程序是由代码变化而来的,但是事实上来说,用 c/C++ 写出的代码是不能被计算机识别的,其中必须经过一系列的过程才能使这个代码能成功的被计算机识别;

这几个过程分别为:

预处理编译汇编链接
在经历过这几个过程之后才能将代码转换为一个可执行程序;

预处理 -E

在预处理阶段时一般会进行:

  • 去注释 - 将源文件中的注释使用"空格"代替;
  • 宏替换 - 若是源文件中存在以#define定义的宏,则将其替换;
  • 头文件展开 - 将头文件进行展开;
  • 条件编译 - 根据条件编译中的条件,留下正确条件;

该些操作一般为文本操作,且该些操作结束后也仍为c/C++;

g++ -E test.cpptest.cpp文件进行预处理,并将预处理后的结果显示在显示器上;
g++ -E test.cpp -o test.itest.cpp文件进行预处理,同时指定生成一个 test.i临时文件;
-E 指令从现在开始进行程序的翻译,如果预处理完成则停止;

在这里插入图片描述
从上图可以看出预处理前后的区别

可以看出两个文件大小的差距,源文件中的代码量大概只有23行,而再进行预处理过后,代码量变成接近三万行;


编译 -S

编译这个过程则是将预处理后的 .i 文件进行翻译,将c/C++代码翻译成汇编代码 .s文件;

g++ -S test.i 或是 g++ -S test.i -o test.stest.i文件编译成汇编语言 , 两种方法都可以生成test.s文件 ; 第二种方法可以指定生成文件的文件名(这里后缀一般不影响);
g++ -S test.cpp -o test.s作用同上,唯一不同的为这里将从test.cpp文件开始进行翻译,途中将要重新进行一次预处理;;
-E 指令从现在开始进行程序的翻译直到编译完成;

请添加图片描述


汇编 -c

在这个阶段过后,.s文件将会被转为可重定向二进制目标文件( .o 文件);

虽然这里转化为了二进制文件,但是仍然不能被计算机直接进行识别;

g++ -c test.s 或是 g++ -c test.i -o test.o将汇编语言文件 test.s 进行汇编生成可重定向二进制目标文件 test.o
od 命令将指定内容文件以八进制、十进制、十六进制、浮点格式或ASCII编码字符方式显示。默认使用的是八进制;
-c 指令从现在开始进行程序翻译,直到汇编结束。

请添加图片描述

[如图所示为使用vim打开时所显示的为二进制]

这里所生成的可重定向二进制文件并不能被执行;

这里或多或少可能会存在权限问题,因为所生成的可重定向二进制文件的权限为666 & (~umask)为664;
即没有运行的权限,为了排除该情况,修改文件权限;

请添加图片描述
但即使修改了文件权限也依然不能运行;
需要打开该文件即可以使用od命令将文件打开;
在这里插入图片描述


链接

这也是程序翻译的最后一个步骤,即将多个.o 或者 .obj 文件合并成一个可执行程序 .exe ;

g++ test.cpp -o test 或 g++ -o test test.cpptest.cpp源文件编译生成 test可执行程序;

然而在链接这一过程中也有分情况,分别为动态链接与静态链接;


动静态链接

在这之前首先要介绍两个命令:

ldd filename file filename
查看该文件所依赖的库文件可以查看文件的可执行程序状态(位数、动态链接等)
请添加图片描述请添加图片描述

一般的连接方式分为两种:

a.动态链接b.静态链接
需要动态库需要静态库

在调用函数中总是会包含各种头文件,但只有头文件是并不能将程序编译通过的;
头文件中只包含了各个函数的声明,而函数的定义一般以库的形式展示;
步骤一般为,在调用函数过后,从头文件中找到函数的声明,再去对应的库中找到函数的定义从而进行调用;

头文件 : 用来提供函数的声明库文件 : 用来提供函数的定义(实现)
请添加图片描述请添加图片描述

自己写的源文件包含头文件,链接库文件才能生成一个可执行程序;

系统\库动态库静态库
Linux.so .a
Windows.dll.lib

在安装vs2019或者vs2022这种编译器时,虽然叫做配置环境,但是本质上是在安装所用语言的头文件以及库文件;

C程序是脱离不开库文件的;

在Linux中,许多的命令也是利用c语言实现的,例如在Linux中使用的ls命令;

请添加图片描述

在汇编过后所生成的可重定向二进制目标文件;

请添加图片描述

#include<iostream>

int main()
{
  std::cout << "it's a test fail" << std:: endl;
  return 0;
}

从该文件中可以看到,该文件包含了一个文件 ,且调用了流插入<<流提取>>;

而这里生成的可重定向二进制文件只是将自己写的源文件中的代码生成可重定向的二进制目标文件;

至于代码中所包含的头文件以及使用流插入流提取并没有进行操作;

该操作将会在最后一步的链接过程中;

链接过程将会把该重定向二进制文件与对应的库文件进行链接最终生成一个可执行程序;(头文件在预处理阶段被展开)

静态链接动态链接
原理在生成可执行文件的时候(链接阶段),把所有需要的函数的二进制代码都包含到可执行文件中去。因此,链接器需要知道参与链接的目标文件需要哪些函数,同时也要知道每个目标文件都能提供什么函数,这样链接器才能知道是不是每个目标文件所需要的函数都能正确地链接。如果某个目标文件需要的函数在参与链接的目标文件中找不到的话,链接器就报错了。目标文件中有两个重要的接口来提供这些信息:一个是符号表,另外一个是重定位表。在编译的时候不直接拷贝可执行代码,而是通过记录一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统,操作系统负责将需要的动态库加载到内存中,然后程序在运行到指定的代码时,去共享执行内存中已经加载的动态库可执行代码,最终达到运行时连接的目的。
缺点静态库的缺点为,若是多个文件同时调用同一个函数,则可能出现在一个项目中出现大量重复代码;动态库链接的缺点即为过于依赖动态库;
方法g++ test.cpp -o test -static
(-static : 表明使用静态链接的方式形成可执行程序)
g++ test.cpp -o test (默认即为动态链接)

在这里插入图片描述

  1. 一般的机器可能会因为没有静态库而导致静态链接失败;
    在Linux中,动态链接必须使用 .so 动态库文件;
    静态链接必须使用 .a 静态库文件;

  2. 若是没有静态库文件则需要进行安装 :

c静态库安装命令C++静态库安装命令
(sudo yum install -y glibc-static)(sudo yum install -y libstdc+±static)

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

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

相关文章

springboot篮球竞赛预约平台springboot033

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…

微火资讯:共享WiFi贴如何盈利,现在到底还能做吗?

共享WiFi贴项目作为一项创新的网络服务模式&#xff0c;近年来在市场上崭露头角。然而&#xff0c;它是否能够长期发展和持续盈利&#xff0c;一直是人们关注的问题。那么&#xff0c;共享WiFi贴到底能不能做呢&#xff1f;让我们一起来探讨一下。 首先&#xff0c;共享WiFi的市…

黑马点评-07缓存击穿问题(热点key失效)及解决方案,互斥锁和设置逻辑过期时间

缓存击穿问题(热点key失效) 缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且重建缓存业务较复杂的key突然失效了,此时无数的请求访问会在瞬间打到数据库,带来巨大的冲击 一件秒杀中的商品的key突然失效了&#xff0c;由于大家都在疯狂抢购那么这个瞬间就会有无数的请求…

KmeansR趋势分析

KmeansR趋势分析 library(KmeansR) df <- data.frame(A runif(2000),B runif(2000),C runif(2000)) KmeansR::KmeansR(df,centers 6,table FALSE)

【JavaEE初阶】 线程安全

文章目录 &#x1f334;线程安全的概念&#x1f333;观察线程不安全&#x1f384;线程不安全的原因&#x1f6a9;修改共享数据&#x1f4cc;原子性&#x1f4cc; 可见性&#x1f4cc;代码顺序性 &#x1f332;解决之前的线程不安全问题⭕总结 &#x1f334;线程安全的概念 线程…

关于ABB速度,加速度,轴监控指令

关于ABB速度&#xff0c;加速度&#xff0c;轴监控 关于轴监控指令要选择启用和关闭&#xff0c;这个指令是为了防止机器人在抓件放件过程中6轴来回旋转&#xff0c;已最佳的姿态运动 收录于合集 #ABB机器人 9个 上一篇关于ABB机器人的IO创建和设置

代码随想录Day15 二叉树 LeetCodeT513 找树左下角的值 T112路径总和 T106 从中序和后序遍历构造二叉树

以上思路来自于:代码随想录 (programmercarl.com) LeetCode T513 找树左下角的值 题目思路: 本题思路:这题我们使用递归法和迭代法解决问题 注意:左下角的值不一定就是一直向左遍历的叶子结点的值,首先可以确定是最后一行的第一个叶子结点的值,也就是最大深度的叶子结点的值 定…

flask入门

第一个Flask项目 创建后项目如下图 static存放静态文件&#xff0c;templates存放Jinja2模板&#xff0c;app.py是整个项目的入口文件 我们略微理解下app.py这里的代码 # 从flask这个包中导入Flask类 from flask import Flask#使用Flask类创建一个app对象 #__name__:代表当前…

Linux下kibana的安装与配置

1. 环境配置 确保Linux服务器上已安装Java 8或更高版本。可以通过运行 java -version 来验证Java的版本。 下载Kibana 7.17.11的压缩文件&#xff0c;可以从Kibana 7.17.11下载 上传服务器&#xff0c;并解压Kibana压缩文件。 2. Kibana配置 编辑Kibana的配置文件 config/k…

JS中使用递归的一次探索

什么是递归&#xff1a;递归的思想是把一个大型复杂问题层层转化为一个与原问题规模更小的问题&#xff0c;问题被拆解成子问题后&#xff0c;递归调用继续进行&#xff0c;直到子问题无需进一步递归就可以解决的地步为止。 说白话就是函数自己调自己。 再翻译白话&#xff1…

【Unity ShaderGraph】| 如何快速制作一个炫酷 模型裁剪效果 实战

前言 【Unity ShaderGraph】| 如何快速制作一个炫酷 模型裁剪效果 实战一、效果展示二、简易裁剪效果三、进阶裁剪效果四、应用实例 前言 本文将使用Unity 的ShaderGraph制作一个模型裁剪的效果&#xff0c;可以直接拿到项目中使用。对ShaderGraph还不了解的小伙伴可以参考这篇…

练[CISCN2019 华东南赛区]Double Secret

[CISCN2019 华东南赛区]Double Secret 文章目录 [CISCN2019 华东南赛区]Double Secret掌握知识解题思路关键paylaod 掌握知识 ​ flask框架报错源码泄露&#xff0c;使用脚本进行RC4加解&#xff0c;ssti使用内置函数进行模板注入 解题思路 打开网站链接&#xff0c;页面就一…

【LeetCode75】第六十九题 或运算的最小翻转次数

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们 a&#xff0c;b&#xff0c;c 三个数&#xff0c;我们可以对 a 和 b 的二进制形态中的任何一位做翻转&#xff0c;问我们最少…

MobileViT v2导出onnx模型时遇Col2Im算子无法导出问题

相关error log索引 onnxruntime.capi.onnxruntime_pybind11_state.InvalidGraph: [ONNXRuntimeError] : 10 : INVALID_GRAPH : This is an invalid model. In Node, ("/classifier/classifier.0/ReduceMean", ReduceMean, "", -1) : ("/layer_5/laye…

hive3.1核心源码思路

系列文章目录 大数据主要组件核心源码解析 文章目录 系列文章目录大数据主要组件核心源码解析 前言一、HQL转化为MR 核心思路二、核心代码1. 入口类&#xff0c;生命线2. 编译代码3. 执行代码 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 对大…

UUID和雪花(Snowflake)算法该如何选择?

博主简介&#xff1a;不写代码没饭吃&#xff0c;一名全栈领域的创作者&#xff0c;专注于研究互联网产品的解决方案和技术。熟悉云原生、微服务架构&#xff0c;分享一些项目实战经验以及前沿技术的见解。关注我们的主页&#xff0c;探索全栈开发&#xff0c;期待与您一起在移…

嵌入式养成计划-38----C++--匿名对象--友元--常成员函数和常对象--运算符重载

八十七、匿名对象 概念&#xff1a;没有名字对象格式 &#xff1a;类名&#xff08;&#xff09;;作用 用匿名对象给有名对象初始化的用匿名对象给对象数组初始化的匿名对象作为函数实参使用 示例 : #include <iostream> using namespace std; class Dog { private:s…

小程序如何设置各种时间参数

在小程序管理员后台->基本设置处&#xff0c;可以设置各种时间。例如待支付提醒时间、待支付取消时间、自动发货时间、自动收货时间、自动评价时间等等。下面具体解释一下各个时间的意思。 1. 待支付提醒时间&#xff1a;在用户下单后&#xff0c;如果一段时间内没有完成支付…

IDEA的使用(一)代码模块的导入、快捷使用、自定义 (IntelliJ IDEA 2022.1.3版本)

目录 1. IDEA项目结构 2. 模块的导入操作 2.1 正规操作 2.2 取巧操作 2.3 出现乱码 2.4 模块改名 3. 代码模板的使用 后缀补全&#xff08;Postfix Completion&#xff09;、实时模板&#xff08;Live Templates&#xff09;菜单里面什么介绍都有&#xff0c;可以自学&a…

C#(Csharp)我的基础教程(四)(我的菜鸟教程笔记)-Windows项目结构分析、UI设计和综合事件应用的探究与学习

目录 windows项目是我们.NET学习一开始必备的内容。 1、窗体类&#xff08;主代码文件窗体设计器后台代码文件&#xff09; 主窗体对象的创建&#xff1a;在Program类里面&#xff1a; Application.Run(new FrmMain());这句代码就决定了&#xff0c;当前窗体是项目的主窗体。…