首页 > 其他分享 >12.2.1 宏定义

12.2.1 宏定义

时间:2024-10-27 09:49:00浏览次数:6  
标签:定义 编译 我们 12.2 指令 源代码 预处理 define

1.#define

这个编译预处理指令啊,其实我们很早就见过了,我们的第一个c语言的程序,那个hello world,它的第一行,他的第一个字符那个井号,就说明它是一条编译预处理指令所有的c语言的编译预处理指令呢
都是以井号开头的,实际上这些井号开头的东西,,它并不是c语言的成分,但是呢任何一个c语言的程序都离不开他们,之所以说它不是c语言的成分,是因为这些东西,你看比如说include,它不是c语言的关键字啊,也不是只有c语言在使用,这些编译预处理指令,其他语言也可以去使用,那么我们之前看到的都是井号include啊,它是这个用来呃引入一个头文件的啊,这是我们到后面讲大程序结构的时候
我们再来说,我们先来看另外一个小东西.叫做#define.呃,这事我们之前没做过啊,我们来做一下.


原本呢我们可能写程序是这样写啊.我们我们要用到一个叫做pi的东西,然后呢我们之前提到过说,那,你如果呃程序里面直接写,比如说我这句printf直接写成说2乘以这个3.14159,那这个3.14159是个什么样的东西,别人可能会有各种各样的想法.所以呢我们更好的方式是把这个常数3.14159呢做成一个constant double啊,做成一个不可变的变量,这是c99 的做法如果你在用ansi c,你在用更老的版本,它没有const这样的东西可以用,那个时候人们就要用这样的方法说,我们要define一个叫做pi的东西,它是3.14159.如果这样子,当然这个程序还是有一定.所以这一行define我们就定义了一个符号,我们把这样定义出来的符号叫做宏.pi是这个宏的名字,后面的数字是它的值.

c语言的程序在编译的时候呢,准确地说在编译之前,因为它叫做编译预处理指令对吧,会做一次编译预处理.在那次预处理里头呢,会把所有你的程序里头的这种pi都替换成那个数字.呃,我们有一个办法,可以去看到在编译过程中留下来的那些临时文件,如果是gcc的话,是需要这么做的.

除了我们最终要拿来运行的那个a.out之外,我们源代码.c,我们还多了一个.i,.o和.s,当然这三个文件它这个排列是按照字母顺序啊,他并不是真正程序编译过程当中产生的那个顺序.首先产生的是点i,然后从.i得到了.s,再从.s呢得到了那个.o,再从.o呢得到了那个a.out.源代码(.c)经过编译预处理做完以后呢产生了临时的一个中间结果的文件,就是把当中所有的编译预处理指令都执行完,比如说define那个宏要拿去做替换的,把它替换掉.然后对.%s才是.c实际编译产生的文件,这是汇编代码文件,然后汇编代码文件去做汇编,变成了一个目标代码文件,这个目标代码文件再经过链接,最后就形成了一个可执行的东西.

所以#define这个东西呢是一个编译预处理指令,它会在编译器开始去编译之前,先把你的源代码做一遍编译预处理,把里面的所有的宏都替换掉.把出现了你定义的那些宏的名字的地方都替换成那个后面的值,后面的那个值可以很复杂,可以带空格,可以带各种标点符号,没关系.反正第一个是单词,后面其他的都是值,然后原封不动地做文本的替换.特别要小心的是,在那个define后面不能加分号,因为这不是一句c的语句,c的语句才用加分号.

2.宏

如:

3.没有值的宏

其实我们还会在程序中看到,我们会定义没有值的宏.如#define _debug.像这种情况呢,我们是告诉编译器说我们有了这个宏了,可是我们不需要它有什么样值,因为我们在后面可能会去检查说这个宏存在还是不存在,它如果存在,我们编译这部分代码,如果不存在,我们可能编译另一部分代码.这是用来做条件编译的,后面有其他的编译预处理指令来检查这个宏是否已经被定义过了.

4.预定义的宏

另外呢,我们的编译器有一些预先定义的宏,呃,它们都是带着翅膀的,就是前面有两个下划线,后面也有两个下划线,好像带着翅膀一样.那么这些宏呢,一般是用来表达一些特殊的东西,可以让编译器替你插入一些特殊的值.

比如说第一个是表达说这个源代码文件的行号,当前所在的那个行的行号,第二个表达的是源代码文件的文件名,第三个和第四个分别表示的是源文件编译的日期和时间.我们可以来试一下这些有意思的预定义宏:

运行结果:

最后一个用来表示编译器是否遵循ansi c标准,然而现在已经基本没用了.



 

标签:定义,编译,我们,12.2,指令,源代码,预处理,define
From: https://blog.csdn.net/qq_73908174/article/details/143253789

相关文章

  • kube-prometheus-stack 自定义 alertmanager 配置推送webhook
    创建AlertmanagerConfig资源在没有使用prometheus-operator的情况下,需要手动配置alertmanager.yaml来路由&发送从prometheus接收的警报。使用prometheus-operator之后,事情变得简单一些。只需要创建AlertmanagerConfig资源,prometheus-operator会自动merge所有的Ale......
  • 化学仿真软件:Aspen Plus二次开发_自定义模型开发
    自定义模型开发1.介绍AspenPlus是一种广泛应用于化工过程模拟和优化的软件工具。在许多情况下,标准模型库中的模型可能无法满足特定工艺的需求。因此,自定义模型开发成为提高仿真精度和效率的重要手段。本节将详细介绍如何在AspenPlus中开发自定义模型,包括模型开发的......
  • 学习笔记(五):自定义构建函数
    若自定义的组件内部UI结构固定,且仅与使用方进行数据传递。则无需单独写一个自定义组件文件,可直接在使用方内进行定义。即UI元素复用机制@Builder,@Builder所装饰的函数遵循build()函数语法规则,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。定义一个自定义构建......
  • WPF+Mvvm案例实战(五)- 自定义雷达图实现
    文章目录1、项目准备1、创建文件2、用户控件库2、功能实现1、用户控件库1、控件样式实现2、数据模型实现2、应用程序代码实现1.UI层代码实现2、数据后台代码实现3、主界面菜单添加1、后台按钮方法改造:2、按钮添加:3、依赖注入3、运行效果4、源代码获取1、项目准......
  • WPF+MVVM案例实战(六)- 自定义分页控件实现
    文章目录1、项目准备2、功能实现1、分页控件DataPager实现2、分页控件数据模型与查询行为3、数据界面实现3、运行效果4、源代码获取1、项目准备打开项目Wpf_Examples,新建PageBarWindow.xaml界面、PageBarViewModel.cs,在用户控件库UserControlLib中创建用......
  • 推荐15个 Vue 常用自定义指令,含实现原理与使用方式
    前言Vue.js是一个流行的前端框架,它的核心理念是通过指令(Directives)来扩展HTML的能力。尽管Vue.js已经内置了一些非常实用的指令(比如v-if,v-show,v-for等),但有时候我们还是需要创建自定义指令来满足特定的需求。今天我们就来聊聊Vue常用的自定义指令,它们能让你的......
  • 提现生成器【APP】自定义生成小游戏提现截图
    今天发个避坑帖!首先看看下面这种收益图,你们肯定见过不少!‘割割’们让你上车,必须得有一些吸引你的东东啊,不然怎么割你吗?其实这种截图都是软件生成的,我网站上分享过非常多的类似软件,什么聊天记录生成的啊,什么ZFB,微信零钱转账记录,余额多少啊。。。。。都可以生成。像这种......
  • 提现生成器【APP】自定义生成小游戏提现截图
    今天发个避坑帖!首先看看下面这种收益图,你们肯定见过不少!‘割割’们让你上车,必须得有一些吸引你的东东啊,不然怎么割你吗?其实这种截图都是软件生成的,我网站上分享过非常多的类似软件,什么聊天记录生成的啊,什么ZFB,微信零钱转账记录,余额多少啊。。。。。都可以生成。像这种......
  • 提现生成器【APP】自定义生成小游戏提现截图
    今天发个避坑帖!首先看看下面这种收益图,你们肯定见过不少!‘割割’们让你上车,必须得有一些吸引你的东东啊,不然怎么割你吗?其实这种截图都是软件生成的,我网站上分享过非常多的类似软件,什么聊天记录生成的啊,什么ZFB,微信零钱转账记录,余额多少啊。。。。。都可以生成。像这种......
  • 提现生成器【APP】自定义生成小游戏提现截图
    今天发个避坑帖!首先看看下面这种收益图,你们肯定见过不少!‘割割’们让你上车,必须得有一些吸引你的东东啊,不然怎么割你吗?其实这种截图都是软件生成的,我网站上分享过非常多的类似软件,什么聊天记录生成的啊,什么ZFB,微信零钱转账记录,余额多少啊。。。。。都可以生成。像这种......