c/c++ 程序运行的过程分析

c/c++编译基础知识

GNU

GNU(GNU’s Not Unix!)是一个由理查德·斯托曼(Richard
Stallman)在1983年发起的自由软件项目,旨在创建一个完全自由的操作系统,包括操作系统的内核、编译器、工具、库、文本编辑器、邮件系统、新闻系统等。GNU项目是自由软件运动的核心,其目标是确保用户有使用、复制、修改和分发软件的自由。

GNU项目的一些关键组件包括:

  1. GCC(GNU Compiler Collection):一套支持多种编程语言的编译器,包括C、C++、Objective-C、Fortran、Ada、Go等。

  2. GDB(GNU Debugger):一个强大的程序调试工具,用于调试C和C++程序。

  3. Glibc(GNU C Library):GNU项目开发的C标准库实现,广泛用于Linux操作系统。

  4. Gawk:一个文本处理工具,类似于Unix的awk。

  5. Grep:一个用于搜索文本的工具,类似于Unix的grep。

  6. Gnuplot:一个绘图工具,用于绘制函数、数据等图形。

  7. Emacs:一个功能强大的文本编辑器。

  8. Bash(Bourne Again Shell):一种Unix shell和命令语言。

  9. GnuPG(GNU Privacy Guard):一个加密软件,用于数据加密和数字签名。

  10. AutoconfAutomake:用于生成配置脚本和Makefile的工具。

GNU项目还开发了Hurd,这是一个旨在替代Unix内核的操作系统内核,但由于种种原因,Hurd并没有得到广泛的应用。相反,Linux内核(由林纳斯·托瓦兹开发)与GNU工具集合成为今天广泛使用的Linux操作系统。

GNU项目强调软件的自由性,其发布的软件遵循GNU通用公共许可证(GPL),这是一种“传染性”的许可证,要求所有基于GPL软件的衍生作品也必须以GPL发布,从而确保软件的自由性得以传递。

GCC

GCC,全称为GNU编译器集合(GNU Compiler
Collection),是一个由GNU项目开发的编程语言编译器系统。它支持多种编程语言,包括但不限于C、C++、Objective-C、Fortran、Ada、Go和D等。GCC是自由软件,遵循GNU通用公共许可证(GPL)发布。

GCC的主要特点包括:

  1. 跨平台:GCC可以在多种操作系统上编译源代码,包括Linux、Windows、macOS等。

  2. 优化:GCC提供了多种优化选项,以提高生成代码的执行效率。

  3. 调试支持:GCC能够生成调试信息,与GDB(GNU Debugger)等调试工具配合使用。

  4. 多种语言支持:GCC支持多种编程语言的编译,使其成为一个多功能的编译器集合。

  5. 自动并行化:GCC的一些版本提供了自动并行化的功能,可以自动将某些循环转换为并行执行的形式。

  6. 内联汇编:GCC支持内联汇编语言,允许开发者在高级语言代码中嵌入汇编指令。

  7. 插件支持:GCC允许通过插件扩展其功能。

  8. 交叉编译:GCC支持交叉编译,即在一种平台上编译出另一种平台上运行的代码。

GCC是许多Linux发行版默认的系统编译器,并且广泛用于嵌入式系统、高性能计算和各种软件开发项目中。由于其强大的功能和灵活性,GCC是开源社区中最受欢迎的编译器之一。

gcc 和 g++

GCC(GNU Compiler Collection)是一个编译器集合,它包括多个不同的编译器,其中最常用的是针对C语言的gcc和针对C++语言的g++。以下是gccg++的简要说明:

  1. gcc

    • 这是GNU项目提供的C语言编译器。
    • 它用于编译C语言源代码文件(通常以.c为扩展名)。
    • gcc支持多种操作系统和硬件平台,可以生成针对不同目标的可执行文件或库文件。
  2. g++

    • g++是GNU编译器集合中的C++语言编译器。
    • 它用于编译C++语言源代码文件(通常以.cpp.cc为扩展名)。
    • g++同样支持跨平台编译,并提供了C++特有的特性支持,如类、模板、异常处理等。

两者的主要区别在于它们支持的语言特性和标准库。gcc专门用于C语言,而g++则用于C++语言。尽管它们在某些底层组件上共享代码,但它们的前端(解析源代码的部分)是不同的,以适应各自语言的语法和特性。

使用示例:

  • 编译C语言程序: sh gcc -o program program.c 这将编译program.c并生成名为program的可执行文件。

  • 编译C++语言程序: sh g++ -o program program.cpp 这将编译program.cpp并生成名为program的可执行文件。

在实际使用中,您可能还会使用到其他选项和参数,例如优化标志(-O2)、调试信息生成(-g)、链接特定库(-L-l)等。此外,g++在编译混合C和C++代码时,也可以调用gcc来编译C语言部分的代码。

gcc 和 g++常见编译选项

gccg++提供了一系列的编译命令选项,用于控制编译过程的不同方面。以下是一些常用的编译命令选项:

  1. 输出可执行文件的名称sh -o <file> 指定输出的可执行文件名。

  2. 优化选项

    • -O0:没有优化。
    • -O1:启用基本优化。
    • -O2:进一步优化。
    • -O3:更多的优化,可能包括更激进的优化策略。
    • -Os:优化生成更小的代码。
  3. 调试信息sh -g 生成调试信息。

  4. 包括搜索路径sh -I <dir> 添加头文件搜索路径。

  5. 库搜索路径sh -L <dir> -l <library> 指定库文件的搜索路径,并链接指定的库。

  6. 链接时的库sh -l <library> 链接时包括特定的库。

  7. 静态链接sh -static 使用静态链接而不是动态链接。

  8. C++ 特定选项(在使用g++时): sh -std=c++11 -std=c++14 -std=c++17 -std=c++20 指定C++语言标准。

  9. 警告选项

    • -Wall:打开几乎所有的警告信息。
    • -Wextra:打开额外的警告信息。
    • -Werror:将所有警告当作错误处理。
  10. 编译特定文件

    -c
    

    只编译和生成目标文件(.o文件),不进行链接。

  11. 生成依赖文件

    -MF <depfile>
    

    生成包含依赖关系的文件。

  12. 使用多个处理器编译

    -j <n>
    

    使用n个处理器进行编译,可以加快编译速度。

  13. 指定架构

    -m32
    -m64
    

    指定生成32位或64位代码。

  14. 禁用标准库

    -nostdlib
    

    编译时不使用标准库。

  15. 内联汇编

    -S
    

    编译后只生成汇编代码。

这些只是gccg++提供的众多选项中的一部分。根据项目的具体需求,您可能还会使用到其他一些选项。在命令行中使用gcc --helpg++ --help可以查看完整的选项列表和说明。

c++ 程序运行的过程分析

  1. 编写完的 c/c++程序想要运行起来,需要四个步骤:预处理、编译、汇编、链接。
    在这里插入图片描述
  2. 编写 c++程序:main.cpp
#include <iostream>
using namespace std;int add (int a, int b)
{return a+b;
}int main()
{int x = 30;int y = 100;int ret = add(x, y);cout << "sum: " << ret << endl;return 0;
}

预处理

在C++编译过程中,预处理是一个重要的步骤,它发生在实际编译之前。以下是预处理的一些主要作用:

  1. 宏替换: 预处理器会处理宏定义(由#define指令定义)和宏展开。例如,如果你在代码中使用了#define PI 3.14159,预处理器会将代码中所有的PI替换为3.14159

  2. 文件包含: 使用#include指令包含标准库头文件或用户自定义的头文件。预处理器会将这些文件的内容插入到该指令的位置。

  3. 条件编译: 预处理器根据条件编译指令(如#ifdef#ifndef#if#else#elif#endif)来决定是否包含特定的代码段。这允许开发者根据不同的编译条件编写不同的代码。

  4. 行控制#line指令可以用来控制编译器报告错误和警告时显示的文件名和行号。

  5. 错误诊断: 使用#error指令可以在编译时生成错误信息。

  6. 编译时间计算#if指令可以用来进行编译时常量的计算和比较。

  7. 版本控制和编译选项: 预处理器可以根据不同的定义来启用或禁用特定的代码段,这通常用于处理不同操作系统或编译器的特性。

  8. 依赖性分析: 预处理器可以生成依赖性信息,这对于自动构建系统来说是有用的,以确保在头文件更改时重新编译依赖的文件。

  9. 函数宏和宏函数: 预处理器处理函数宏和宏函数的调用和展开。

  10. 预定义宏
    编译器会定义一些预定义宏,如__FILE____LINE____DATE____TIME__等,它们在预处理时被替换为当前文件名、行号、日期和时间。

预处理的结果是一个或多个预处理过的源文件,这些文件随后将被编译器进行语法分析、语义分析和代码生成等后续编译步骤。预处理是C++源代码转换为可执行程序的第一步,对于编译器正确理解源代码结构至关重要。

  1. 预处理命令g++ -E main.cpp -o main.i
  2. 生成文件main.i,仍是文本文件,可以用任意文本编辑器打开。

编译

编译是将高级语言代码转换成低级代码(通常是汇编代码或中间代码)的过程,侧重于语言特性的处理和代码优化。 编译阶段的作用:

  • 语法分析:检查代码是否符合C++语言的语法规则。
  • 词法分析:将源代码分解成一系列的词素(tokens)。
  • 语义分析:确保代码符合C++的语义规则,比如类型检查和作用域解析。
  • 抽象语法树(AST)构建:将源代码转换成AST,这是一种树状结构,表示程序的逻辑。
  • 优化:对AST进行优化,以提高程序性能或减少资源消耗。
  • 代码生成:将优化后的AST转换成中间代码或汇编代码。

在一些编译器实现中,编译阶段可能直接生成机器代码,而在其他情况下,编译器可能先生成汇编代码,然后由汇编器转换成机器代码。无论哪种情况,编译和汇编都是将源代码转换成可执行程序的必要步骤。

  1. 编译命令g++ -S main.cpp -o main.s
  2. 生成文件main.s

汇编

汇编是将汇编语言代码转换成机器代码的过程,侧重于目标机器的指令集和内存管理。 汇编阶段的作用:

  • 转换为汇编语言:将编译器生成的中间代码转换成目标机器的汇编语言。
  • 符号替换:将代码中的符号(如变量名和常量)替换为内存地址或立即数。
  • 地址分配:为代码和数据分配具体的内存地址。
  • 生成汇编文件:创建包含汇编指令的文件,这些指令可以被汇编器进一步处理。
  • 错误检测:检测汇编代码中的错误,如非法指令或不正确的地址引用。
  • 准备链接:生成的目标文件通常是可重定位的,为后续的链接阶段做准备。
  1. 汇编命令g++ -c main.cpp -o main.o 或者直接用汇编文件命令as main.s -o main.o
  2. 生成文件main.o

链接

C++编译的链接阶段是将编译器生成的目标文件(通常是.o.obj文件)组合成最终可执行文件或库文件的过程。以下是链接阶段的主要作用:

  1. 符号解析: 链接器解析目标文件中的符号引用,确保每个外部符号(变量和函数)都能正确地关联到其定义。

  2. 地址和空间分配: 链接器为程序中的代码和数据分配最终的内存地址,并决定它们在可执行文件中的布局。

  3. 代码和数据合并: 链接器将所有目标文件中的代码和数据合并成一个单一的可执行文件或库文件。

  4. 库链接: 如果程序依赖于外部库,链接器会将这些库中的代码和数据与目标文件合并。这包括静态库和动态库的链接。

  5. 重定位: 链接器处理重定位项,将代码和数据中的相对地址转换为绝对地址。

  6. 生成可执行文件: 对于最终的可执行文件,链接器生成一个可在操作系统上运行的程序。

  7. 生成库文件: 对于库文件,链接器生成一个包含多个函数和变量定义的文件,这些可以在其他程序中使用。

  8. 符号表生成: 链接器生成一个符号表,列出了程序中所有的符号及其地址。

  9. 调试信息整合: 如果编译时带有调试信息,链接器会整合这些信息到最终的可执行文件或库中。

  10. 资源文件处理
    链接器处理程序中使用的资源文件,如图形、声音等,并将它们整合到最终的程序中。

  11. 优化
    某些链接器或与之集成的工具可能会进行进一步的优化,如死代码消除。

  12. 生成调试符号
    如果需要,链接器可以生成调试符号文件,如DWARF格式的符号信息,以支持后续的调试工作。

  13. 错误检测
    链接器在链接过程中会检测未解决的外部引用或其他链接错误,并报告这些问题。

链接是编译过程的最后阶段,确保了所有编译后生成的片段能够正确地组合在一起,形成一个完整的程序。链接后的程序可以直接在目标机器上运行或被其他程序作为依赖库使用。

  1. 链接命令g++ -o main main.o
  2. 生成文件main

验证

  1. 文件目录
.
├── main
├── main.cpp
├── main.i
├── main.o
└── main.s
  1. 验证可执行程序./main
  2. 输出结果sum:130
admin@bogon test % ls
main		main.cpp	main.i		main.o		main.s
admin@bogon test % ./main
sum: 130

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ROS——坐标系管理、监听与广播、常用可视化工具

坐标系管理 TF功能包 小海龟追踪实验 ros版本(20.04)的tf安装命令: sudo apt-get install ros-noetic-turtle-tf 解决因python版本出现的无法生成跟随海龟&#xff1a; sudo ln -s /usr/bin/python3 /usr/bin/python ( -s 软链接,符号链接) ln命令&#xff08;英文全拼&#…

7 动态规划

下面的例子不错&#xff1a; 对于动态规划&#xff0c;能学到不少东西&#xff1b; 你要清楚每一步都在做什么&#xff0c;划分细致就能够拆解清楚&#xff01; xk. - 力扣&#xff08;LeetCode&#xff09; labuladong的算法笔记-动态规划-CSDN博客 动态规划是一种强大的算法…

JDK都出到20多了,你还不会使用JDK8的Stream流写代码吗?

目录 前言 Stream流 是什么&#xff1f; 为什么要用Steam流 常见stream流使用案例 映射 map() & 集合 collect() 单字段映射 多字段映射 映射为其他的对象 映射为 Map 去重 distinct() 过滤 filter() Stream流的其他方法 使用Stream流的弊端 前言 当你某天看…

【图解大数据技术】Hive、HBase

【图解大数据技术】Hive、HBase Hive数据仓库Hive的执行流程Hive架构数据导入Hive HBaseHBase简介HBase架构HBase的列式存储HBase建表流程HBase数据写入流程HBase数据读取流程 Hive Hive是基于Hadoop的一个数据仓库工具&#xff0c;Hive的数据存储在HDFS上&#xff0c;底层基于…

价格预言机的使用总结(一):Chainlink篇

文章首发于公众号&#xff1a;Keegan小钢 前言 价格预言机已经成为了 DeFi 中不可获取的基础设施&#xff0c;很多 DeFi 应用都需要从价格预言机来获取稳定可信的价格数据&#xff0c;包括借贷协议 Compound、AAVE、Liquity &#xff0c;也包括衍生品交易所 dYdX、PERP 等等。…

Linux 防火墙配置指南:firewalld 端口管理应用案例(二十个实列)

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f427;Linux基础知识(初学)&#xff1a;点击&#xff01; &#x1f427;&#x1f427;Linux高级管理专栏&#xff1a;点击&#xff01; &#x1f510;Linux中firewalld防火墙&#xff1a;点击&#xff01; ⏰️…

adb不插usb线通过wifi调试

说起做手机开发也有好多年了&#xff0c;说来惭愧&#xff0c;我最近才知道安卓手机是可以不插数据线进行开发调试的。起因是公司近期采购了一批安卓一卡通设备&#xff0c;需要对其进行定制开发APP,但是由于我插USB调试发现没有反应。通过询问厂家才知道可以通过WIFI进行调试。…

去除gif动图背景的工具网站

选择视频或GIF - 取消屏幕 (unscreen.com)https://www.unscreen.com/upload

Upload-Labs靶场闯关

文章目录 Pass-01Pass-02Pass-03Pass-04Pass-05Pass-06Pass-07Pass-08Pass-09Pass-10Pass-11Pass-12Pass-13Pass-14Pass-15Pass-16Pass-17Pass-18Pass-19Pass-20 以下是文件上传绕过的各种思路&#xff0c;不过是鄙人做题记下来的一些思路笔记罢了。 GitHub靶场环境下载&#x…

进程控制-fork函数

一个进程&#xff0c;包括代码、数据和分配给进程的资源。 fork &#xff08;&#xff09;函数通过系统调用创建一个与原来进程几乎完全相同的进程&#xff0c;也就是两个进程可以做完全相同的事&#xff0c;但如果初始参数或者传入的变量不同&#xff0c;两个进程也可以做不同…

通过卷防水上限,解锁手机的新玩法?IP68之间亦有不同

当手机的日常防水已经成了基本功&#xff0c;防水能力的上限便成了新的赛道。 毕竟再谨慎的人&#xff0c;也可能会有手滑的时候。这个时候&#xff0c;一台有着IP68级防水的手机&#xff0c;就能给你提供一份安心。 【IP68是标准上限&#xff0c;不是手机防水上限】 IP68是…

使用LoFTR模型进行图像配准、重叠区提取

LoFTR模型源自2021年CVPR提出的一篇论文LoFTR: Detector-Free Local Feature Matching with Transformers&#xff0c;其基于pytorch实现图像配准&#xff0c;与基于superpointsuperglue的方法不同&#xff0c; 是一个端到端的图像配准方法。与LoFTR官方库相关的有loftr2onnx库…

【MYSQL】InnoDB引擎为什么选可重复读作为默认隔离级别

InnoDB引擎为什么选可重复读作为默认隔离级别 一般的DBMS系统&#xff0c;默认都会使用读提交&#xff08;Read-Comitted&#xff0c;RC&#xff09;作为默认隔离级别&#xff0c;如Oracle、SQL Server等&#xff0c;而MySQL却使用可重复读&#xff08;Read-Repeatable&#x…

基于GWO灰狼优化的多目标优化算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1灰狼优化算法原理 4.2 多目标优化问题(MOP)的帕累托最优解 4.3 基于GWO的多目标优化算法 5.完整程序 1.程序功能描述 基于GWO灰狼优化的多目标优化算法matlab仿真&#xff0c;目标函数…

浏览器打不开网页、但是电脑有网络,解决办法(win11)

2023.07.06测试有效 华为电脑拿去免费拆机保养后&#xff0c;发现浏览器连接不上网了&#xff0c;但是&#xff01;微信又能登录得上&#xff0c;也就是说电脑还是有网的。 原文链接 一、问题截图 二、解决方法 1.右键打开“网络和Internet设置” 2.打开“代理” 3.将该选项设…

[数据结构] 基于交换的排序 冒泡排序快速排序

标题&#xff1a;[数据结构] 基于交换的排序 冒泡排序&&快速排序 水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 &#xff08;一&#xff09;冒泡排序 优化后实现&#xff1a; &#xff08;二&#xff09;快速排序 I、实现方法&#xff1a; &#…

24-7-6-读书笔记(八)-《蒙田随笔集》[法]蒙田 [译]潘丽珍

文章目录 《蒙田随笔集》阅读笔记记录总结 《蒙田随笔集》 《蒙田随笔集》蒙田&#xff08;1533-1592&#xff09;&#xff0c;是个大神人&#xff0c;这本书就是250页的样子&#xff0c;但是却看了好长好长时间&#xff0c;体会还是挺深的&#xff0c;但看的也是不大仔细&…

C++笔试强训2

文章目录 一、选择题二、编程题 一、选择题 和笔试强训1的知识点考的一样&#xff0c;因为输出的是double类型所以后缀为f,m.n对其30个字符所以m是30&#xff0c;精度是4所以n是4&#xff0c;不加符号默认是右对齐&#xff0c;左对齐的话前面加-号&#xff0c;所以答案是-30.4f…

如何使用HippoRAG增强LLM的记忆

大型语言模型&#xff08;LLM&#xff09;已经证明是一种非常宝贵的思考工具。经过大量文本、代码和其他媒体数据集的训练&#xff0c;它们能够创作出接近人类水平的文章、翻译语言、生成图像&#xff0c;还能以信息丰富的方式回答人们提出的问题&#xff0c;甚至可以编写不同类…

容器:stack

以下是关于stack容器的一些总结&#xff1a; stack容器比较简单&#xff0c;主要包括&#xff1a; 1、构造函数&#xff1a;stack [staName] 2、添加、删除元素: push() 、pop() 3、获取栈顶元素&#xff1a;top() 4、获取栈的大小&#xff1a;size() 5、判断栈是否为空&#x…