程序的编译、链接

目录

前言:

前置知识回顾

宏定义常量

宏定义语句

宏定义函数

条件编译

应用场景

编译过程概览

预编译阶段

编译阶段

 汇编阶段

 链接阶段


前言:

在ANSI C的任何一种实现中,存在两种不同的环境,第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令;第2种是执行环境,它用于实际执行代码,将磁盘中的可执行文件装载到内存中,CPU才能通过总线读取内存中的指令,才能真正执行程序;本文重点阐述程序的翻译坏境;

前置知识回顾

#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro);
命名习惯: 宏名全部大写
//宏的声明:#define name( parament-list ) stuff
//其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中;
//注意:参数列表的左括号必须和宏名name紧邻;
//如果宏名与参数列表之间有任何空白存在,参数列表就会被解释为stuff的一部分;

宏定义常量

# define ROW 10            //宏定义整型常量
# define PI  3.14          //宏定义浮点型常量
# define STR "hello world" //宏定义字符串
int main()
{printf("%d %f %s\n", ROW, PI, STR);return 0;
}
运行结果:

宏定义语句

# define PRINTF printf("Hello Linux!\n");
int main()
{int i = 10;PRINTF;return 0;
}

运行结果:

宏定义函数

宏可以接收参数且不用指定参数类型;

# define ADD(x,y) ((x)+(y))
int main()
{int m = 10;int n = 10;float d1 = 4.5;float d2 = 5.5;printf("%d\n", ADD(m,n));printf("%f\n", ADD(d1, d2));return 0;
}

运行结果:

条件编译

编译程序时使用条件编译指令选择性的将一条语句/一组语句编译或者放弃;
//常见的条件编译指令
#if:    如果条件为真,则执行相应的操作;
#elif:   类似于else if的用法,当前面条件为假,再判断该条件是否为真,如果是真,则执行相应操作;
#else:   如果前面所有条件均为假,则执行相应操作;
#ifdef:  如果该宏已定义,则执行相应操作;
#ifndef: 如果该宏没有定义,则执行相应操作;
#endif : 结束对应的条件编译指令(不能省略);

应用场景

# define VERSION1 1
//# define VERSION2 2
int main()
{
#ifdef VERSION1printf("Hello Version1.0\n");
#elif VERSION2printf("Hello Version2.0\n")
#else printf("Hello Free Version");
#endifreturn 0;
}

运行结果:

//# define VERSION1 1
//# define VERSION2 2
int main()
{
#ifdef VERSION1printf("Hello Version1.0\n");
#elif VERSION2printf("Hello Version2.0\n")
#else printf("Hello Free Version\n");
#endifreturn 0;
}

运行结果:

编译过程概览

将一个.c文件翻译为可执行文件,需要经过预编译(prepressing) 、编译(compliation)、汇编(assernbly)、链接(linking)四个阶段;

预编译阶段

  • 头文件展开
  • 去掉注释
  • 宏替换
  • 条件编译
 //vim编辑器编写test.c文件# include <stdio.h># define M 100int main(){printf("%d\n",M);                                                                                                                           //printf("hello Linux!\n");//printf("hello Linux!\n");//printf("hello Linux!\n");printf("hello world!\n"); return 0;}

Linux环境使用选项 gcc -E test.c -o test.i

此条语句的含义为从现在开始进行程序的翻译过程,当预处理结束时,停止程序的翻译过程;

上图生成test.i文件,使用vim编辑器打开test.i文件;

注释被删除掉,宏定义的M被替换为100,使用选项 vim /usr/include/stdio.h 打开c标准库对比发现头文件被替换;

使用vim编辑器编写code.c代码,code.c代码使用条件编译指令;

//vim编辑器编写code.c代码
# define VERSION1 1
//# define VERSION2 2
int main()
{
#ifdef VERSION1printf("Hello Version1.0\n");
#elif VERSION2printf("Hello Version2.0\n")
#else printf("Hello Free Version\n");
#endifreturn 0;
}

编译阶段

1. 词法分析:词法分析器处理test.i文件,将字符串切割成一个个记号(mark)

      例如:sum=a+b;会产生五个记号:"sum" "=" "a" "+" "b"
2. 语法分析:语法分析器将产生的记号组织成一个个表达式,以表达式为节点,生成一颗语法树
3. 语义分析:语义分析器处理声明以及数据类型、给语法树的节点赋予数据类型
4. 中间代码:根据语法树生成中间代码,以上的步骤是硬件平台无关的,而中间代码之后的处理则需要根据程序运行的硬件平台来决定;
5. 代码生成器:代码生成器将中间代码转换成对应硬件平台的汇编代码test.s

Linux环境使用选项 gcc -S test.c -o test.s

此条语句的含义为从现在开始进行程序的翻译过程,当编译结束时,停止程序的翻译过程;

 汇编阶段

汇编器:汇编器根据 汇编指令与机器指令的对照表 将汇编代码翻译成机器指令,生成目标文件test.o;

目标文件由若干个段(section)组成,每个段中存放不同的内容;

目标文件中的基本段类型:文件头、代码段、数据段、bss段、常量段、段表、符号表、重定位表;

文件头:文件头位于目标文件开始位置,它定义了elf魔数,目标文件的属性、运行的软硬件平台、程序入口地址、段表的位置及长度、段的数量;

代码段:存放  机器指令

数据段:   存放 已经初始化的全局变量以及静态变量

常量段:存放  字符串常量以及被const修饰的变量

bss段: 存放  未初始化的全局变量以及静态变量所占用的内存大小

段表:    记录了目标文件中所有段的地址以及属性(读写or可执行)等信息;

符号表:记录与程序相关的所有符号(如变量、函数名),变量或者函数所对应的地址和属性

重定位表:重定位表用于指示需要进行重定位的指令或数据,记录了位置信息、长度以及对应的符号引用;

Linux环境使用选项 gcc -c test.c -o test.s

此条语句的含义为从现在开始进行程序的翻译过程,当汇编结束时,停止程序的翻译过程;

 链接阶段

链接器:合并输入的.o文件、确定符号内存地址、进行符号重定位,输出可执行文件;

 Linux环境使用选项 gcc test.c -o test.exe

 

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

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

相关文章

GPT-5、开源、更强的ChatGPT!OpenAI公布2024年计划

年终岁尾&#xff0c;正值圣诞节热闹气氛的OpenAI写下了2024年的发展清单。 OpenAI联合创始人兼首席执行官Sam Altman在社交平台公布&#xff0c;AGI&#xff08;稍晚一些&#xff09;、GPT-5、更好的语音模型、更高的费率限制&#xff1b; 更好的GPTs&#xff1b;更好的推理…

大数据- Hadoop入门

目录 &#x1f436;2.1 hadoop的简介 1. 概述 2. 什么是分布式&#xff1f; 3. Hadoop的指代 &#x1f436;2.2 hadoop的发展历程 &#x1f436;2.3 hadoop的版本介绍 &#x1f436;2.4 hadoop的常用端口号 &#x1f436;2.5 hadoop的设计目的 &#x1f436;2.6 hadoo…

Java集合/泛型篇----第二篇

系列文章目录 文章目录 系列文章目录前言一、说说List,Set,Map三者的区别二、Array与ArrayList有什么不一样?三、Map有什么特点四、集合类存放于 Java.util 包中, 主要有几 种接口前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。…

upload-labs Pass-03(黑名单验证,特殊后缀)问题纠正

php任何后缀名解析 背景&#xff1a;为了验证php解析不依靠后缀名&#xff0c;可以是任何后缀名&#xff0c;纠正upload-labs Pass-03&#xff08;黑名单验证&#xff0c;特殊后缀&#xff09;里所说的几个固定的后缀名理论是错误的。1 部署1.1 环境准备1.1.1 系统、内核&#…

【音视频 ffmpeg 学习】 跑示例程序 持续更新中

环境准备 在上一篇文章 把mux.c 拷贝到main.c 中 使用 attribute(unused) 消除警告 __attribute__(unused)/** Copyright (c) 2003 Fabrice Bellard** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated docu…

计算机毕业设计-----ssm流浪狗领养系统

项目介绍 我国的动物管理正处于起步阶段&#xff0c;注册在线的宠物数量非常有限&#xff0c;信息也很封闭&#xff0c;因此必须发挥民间力量扩容&#xff0c;加强宠物信息的宣传力度&#xff0c;使更多爱护动物的好心人可以领养宠物&#xff0c;同时也就收纳有家宠物信息&…

Efficient Classification of Very Large Images with Tiny Objects(CVPR2022补1)

文章目录 Two-stage Hierarchical Attention SamplingOne-stageTwo-Stage内存需求 Efficient Contrastive Learning with Attention Sampling Two-stage Hierarchical Attention Sampling 一阶段缩放是hw&#xff0c;提取的特征是h1w1&#xff0c; 二阶段缩放是uv&#xff08;…

iPortal内置Elasticsearch启动失败的几种情况——Linux

作者&#xff1a;yx 文章目录 前言一、端口占用二、ES启动过慢三、磁盘占用过高&#xff0c;导致ES变为只读模式 前言 在Linux环境启动iPortal后有时会出现搜索异常的情况&#xff0c;如下截图&#xff0c;这是因为Elasticsearch&#xff08;以下简称“ES”&#xff09;没启动…

共享单车之数据可视化

文章目录 第1关&#xff1a;绘制地图第2关&#xff1a;绘制流量最高的五条线路的路程图 第1关&#xff1a;绘制地图 任务描述 本关任务&#xff1a;使用JSP在百度地图上绘制一条共享单车起始路程。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 如何创建地…

进阶学习——Linux系统服务器硬件认识与RAID磁盘

目录 一、服务器知识补充 1.硬件 2.服务器常见故障 二、认识RAID 1.什么是RAID 2.RAID的优点 3.RAID的实现方式 三、RAID磁盘陈列 1.RAID 0 磁盘陈列介绍——RAID 0 2.RAID 1 磁盘陈列介绍——RAID 1 3.RAID 5 磁盘陈列介绍——RAID 5 4.RAID 6 磁盘陈列介绍——RA…

vr体验馆用什么软件计时计费,如遇到停电软件程序如何恢复时间

vr体验馆用什么软件计时计费&#xff0c;如遇到停电软件程序如何恢复时间 一、软件程序问答 如下图&#xff0c;软件以 佳易王vr体验馆计时计费软件V17.9为例说明 1、软件如何计时间&#xff1f; 点击相应编号的开始计时按钮即可 2、遇到停电再打开软件时间可以恢复吗&…

【开源】基于Vue+SpringBoot的公司货物订单管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 客户管理模块2.2 商品维护模块2.3 供应商管理模块2.4 订单管理模块 三、系统展示四、核心代码4.1 查询供应商信息4.2 新增商品信息4.3 查询客户信息4.4 新增订单信息4.5 添加跟进子订单 五、免责说明 一、摘要 1.1 项目…

Redis经典五大类型源码及底层实现(一)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理、数据库技术&#x1f525;如果感觉博主的文章还不错的…

Linux CPU 数据 Metrics 指标解读

过去从未仔细了解过使用 top 和 htop 等命令时显式的CPU信息&#xff0c;本文我们详解解读和标注一下各个数据项的含义&#xff0c;同时和 Ganglia 显式的数据做一个映射。开始前介绍一个小知识&#xff0c;很多查看CPU的命令行工具都是 cat /proc/stat 里的数据&#xff0c;所…

Spring-6-事务管理

事务是构建可靠企业级应用程序的最关键部分之一。 最常见的事务类型是数据库操作。 在典型的数据库更新操作中&#xff0c;首先数据库事务开始&#xff0c;然后数据被更新&#xff0c;最后提交或回滚事务(根据数据库操作的结果而定)。但是&#xff0c;在很多情况下&#xff0…

java中的缓冲类HeapByteBuffer和DirectByteBuffer的区别

使用之前写的文章里的例子 https://blog.csdn.net/zlpzlpzyd/article/details/135292683 HeapByteBuffer import java.io.File; import java.io.FileInputStream; import java.io.Serializable; import java.nio.ByteBuffer; import java.nio.channels.FileChannel;public clas…

【hcie-cloud】【12】华为云Stack故障处理【故障处理通用处理原则、常见华为云Stack故障处理(计算域故障场景)】【上】

文章目录 前言故障处理通用处理原则故障处理流程故障信息收集及故障范围、类型识别ManageOne运维面收集告警信息AutoOps工具故障场景信息收集AutoOps工具自动化采集HCS信息 (1)AutoOps工具自动化采集HCS信息 (2)故障初期定位方向故障恢复例行维护讨论: 哪一环比较重要&#xff…

关于表格太大了jupyter无法单次处理的问题

记录下自己的心路历程…耗时耗精力 我用的数据库单个表格就很大&#xff0c;一个表格有30多G&#xff0c;jupyter无法处理这么大的表格&#xff0c;会直接把电脑的进程全部结束掉&#xff0c;结束掉要是能运行成功倒也行啊&#xff0c;然鹅…给我报错说处理不了&#xff0c;罢工…

【SpringCloud】从实际业务问题出发去分析Eureka-Server端源码

文章目录 前言1.EnableEurekaServer2.初始化缓存3.jersey应用程序构建3.1注册jeseryFilter3.2构建JerseyApplication 4.处理注册请求5.registry&#xff08;&#xff09; 前言 前段时间遇到了一个业务问题就是k8s滚动发布Eureka微服务的过程中接口会有很多告警&#xff0c;当时…

next.js 开发网站的hello world

本文介绍建立一个简单的next.js 工程&#xff0c;以及简单修改。然后也简单说了2种路由方式的选择。 开始next.js工程前需要node.js &#xff0c; 还需要编辑器&#xff0c;我这里选择的是visual code。如果没有安装node.js 请参考下&#xff1a; visual code 下的node.js的he…