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.mzph.cn/bicheng/41629.shtml

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

相关文章

adb shell ps -T打印出来参数的含义,以及D,T,Z代表的状态含义是什么?

在Android系统中&#xff0c;使用adb shell ps命令可以查看当前系统中运行的进程信息。当你添加-T选项时&#xff08;注意&#xff0c;标准的ps命令在Android的adb shell中可能不直接支持-T选项&#xff0c;这通常与Linux中的ps命令略有不同&#xff09;&#xff0c;你可能是想…

线性代数基础概念:矩阵

目录 线性代数基础概念&#xff1a;矩阵 1. 矩阵的定义 2. 矩阵的运算 3. 矩阵的特殊类型 4. 矩阵的秩 5. 矩阵的初等变换 6. 矩阵的特征值与特征向量 7. 矩阵的应用 8. 矩阵总结 总结 线性代数基础概念&#xff1a;矩阵 矩阵是线性代数中的另一个重要概念&#xff0…

学java的第3天 后端商城小程序工作

1.数据库的大坑 特殊字段名 ’我的图片表中有一个字段是描述我写成desc了&#xff0c;正好是mysql中的关键字 就不能使用了 2.后端编写 2.1可以把请求分开 在商品浏览页中 只显示商品的大致信息 当用户再点击其他按钮时在发出请求 2.2把请求合并 把数据整合到一起 利用ass…

Python爬虫教程第1篇-基础知识

文章目录 什么是爬虫爬虫的工作原理用途搜索引擎爬虫Robots协议HTTP的请求过程URL的含义HTTP常见请求头爬虫常用的技术 什么是爬虫 信息的交互是通过web网页、或者移动端等不同的客户端端形式进行交互&#xff0c;这个过程是一个人与网路正常的交互行为。而爬虫可以用来模拟人…

linux-5.10.110内核源码分析 - Freescale ls1012a pcie host驱动

1、dts pcie设备树 1.1、pcie设备树 pcie1: pcie3400000 {compatible "fsl,ls1012a-pcie";reg <0x00 0x03400000 0x0 0x00100000 /* controller registers */0x40 0x00000000 0x0 0x00002000>; /* configuration space */reg-names "regs", &…

JVM原理(十七):JVM虚拟机即时编译器详解

编译器无论在何时、在何种状态下把Class文件转换成与本地基础设施相关的二进制机器码&#xff0c;他都可以视为整个编译过程的后端。 后端编译器编译性能的好坏、代码优化质量的高低却是衡量一款商用虛拟机优秀与否的关键指标之一。 1. 即时编译器 即时编译器是一个把Java的…

Linux进程(1)(结构-操作系统-进程)

目录 1.体系结构 2.操作系统&#xff08;Operator System&#xff09; 1&#xff09;概念&#xff1a; 2&#xff09;结构 示意图&#xff08;不完整&#xff09; 3&#xff09;尝试理解操作系统 4&#xff09;系统调用和库函数概念 3.认识进程 1.启动 2.进程创建的代码…

Mojo 编程语言:AI 开发者的必备利器

目录 1. Mojo 的背景与发展 1.1 编程语言的演变 1.2 Mojo 的诞生 2. Mojo 的核心特点 2.1 高性能计算 2.2 易用性 2.3 灵活性 3. Mojo 的关键技术 3.1 静态类型系统 3.2 并行计算 3.3 高效的内存管理 3.4 GPU 加速 4. Mojo 的应用场景 4.1 数据处理与分析 4.2 机…

王道考研数据机构:中缀表达式转为后缀表达式

实现方法&#xff1a; 初始化一个栈&#xff0c;用于保存暂时还不能确定运算顺序的运算符。从左到右处理各个元素&#xff0c;直到末尾。可能遇到三种情况: 遇到操作数。直接加入后缀表达式遇到界限符。遇到“(”直接入栈;遇到“)”则依次弹出栈内运算符并加入后缀表达式&…

C#用反射机制调用dll文件的字段、属性和方法

1、创建dll文件 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace CLStudent {public class Student{//字段public string Name "Tom";//属性public double ChineseScore { get; s…

Nginx-http_auth_basic_module使用

文章目录 前言一、ngx_http_auth_basic_module二、指令1.auth_basic1.auth_basic_user_file 示例生成密码文件配置basic认证浏览器验证 总结 前言 nginx可以通过HTTP Basic Authutication协议进行用户名和密码的认证。 一、ngx_http_auth_basic_module 生效阶段&#xff1a; …

【linux/shell】linux如何去除字符串中空格

在Linux中&#xff0c;去除字符串中的空格可以使用多种方法&#xff0c;以下是一些常见的命令和技巧&#xff1a; 1. 使用 tr 命令&#xff1a; tr 命令可以用来替换或删除字符。要删除空格&#xff0c;可以使用&#xff1a; echo "字符串" | tr -d 2. 使用 se…

【C++】开源:nlohmann/json数据解析库配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍nlohmann/json数据解析库配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&am…

计算机组成原理--概述

&#x1f308;个人主页&#xff1a;小新_- &#x1f388;个人座右铭&#xff1a;“成功者不是从不失败的人&#xff0c;而是从不放弃的人&#xff01;”&#x1f388; &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f3c6;所属专栏&#xff1…

Jetpack Compose实战教程(五)

Jetpack Compose实战教程&#xff08;五&#xff09; 第五章 如何在Compose UI中使用基于命令式UI的自定义View 文章目录 Jetpack Compose实战教程&#xff08;五&#xff09;一、前言二、本章目标三、开始编码3.1 先让自定义控件能跑起来3.2给自定义控件使用compose的方式赋值…

在linux系统centos上面安装php7gmp扩展

ps:在ubuntu上面安装gmp(最简单) $ sudo apt-get install php7.0-gmp然后再php.ini添加extensionphp_gmp.so <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<…

C#Modbus通信

目录 1&#xff0c;辅助工具。 2&#xff0c;初识Modbus。 3&#xff0c;基于ModbusRTU的通信。 3.1&#xff0c;RTU与ASCII模式区别 3.2&#xff0c;Modbus存储区 3.3&#xff0c;报文格式 3.4&#xff0c;异常代码 3.5&#xff0c;详细文档连接 。 3.6&#xff0c;代…

2024 年第十四届亚太数学建模竞赛(中文赛项)浅析

需要完整B题资料&#xff0c;请关注&#xff1a;“小何数模”&#xff01; 本次亚太(中文赛)数学建模的赛题已正式出炉&#xff0c;无论是赛题难度还是认可度&#xff0c;该比赛都是仅次于数模国赛的独一档&#xff0c;可以用于国赛前的练手训练。考虑到大家解题实属不易&…

纸飞机社工库

收集了一些比较好用的纸飞机社工库&#xff0c;有纸飞机的可以加一下 Space X 隐私信息查询平台https://t.me/SpaceSGK_bot?startKhbOsEdELmingeek社工库 https://t.me/ingeeksgkbot?startNzM3ODE5NDM5Nw Botnet免费社工机器人https://t.me/SGK_0001_bot?start7378194397暗…

TZDYM001矩阵系统源码 矩阵营销系统多平台多账号一站式管理

外面稀有的TZDYM001矩阵系统源码&#xff0c;矩阵营销系统多平台多账号一站式管理&#xff0c;一键发布作品。智能标题&#xff0c;关键词优化&#xff0c;排名查询&#xff0c;混剪生成原创视频&#xff0c;账号分组&#xff0c;意向客户自动采集&#xff0c;智能回复&#xf…