【C语言】宏定义

  • 🚩 WRITE IN FRONT🚩   

  • 🔎 介绍:"謓泽"正在路上朝着"攻城狮"方向"前进四"🔎
  • 🏅 荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评百大博主、华为云享专家、阿里云专家博主、掘金优秀创作者、全网粉丝量6w+、全网访问量100w+🏅
  • 🆔 本文章内容由 謓泽 原创 如需相关转载请提前告知博主 ⚠
  • 📝 个人主页:謓泽的博客📃
  • 📣 专栏系列:【C】系列 📃
  • 🧑‍💻 Gitee:謓泽 (wsxsx) - Gitee.com⭐️
  • 🎁 点赞👍+ 收藏⭐️+ 留言📝​

目录

🍑宏定义不带参数

🍈优点

🍑定义宏 

🍈说明

🍈命名事项

🍻字符串宏常量

🍈practice[练习]

🍻#undef


🍑宏定义不带参数

        说明:宏定义指令的 #define 用来定义一个标识符和一个字符串,我们可以以这个标识符来表示这个字符串,在程序当中每次遇到该标识符的时候就用来所定义的字符串来进行替换它。宏定义的作用相当于给指定的字符串起了一个别名。

不带参数的宏的定义方式如下(这也是我们经常用到的宏定义)

#define 宏名 字符串 //没有分号,说没有分号倒不如说最好不要加分号

        这里说下原因吧:因为宏定义它并不是C语言的语句,所以不用加分号。 

  • 表示这是一条预处理命令。
  • 宏名实际上就是一个标识符,必须要符合C语言当中标识符的语法规定的。

        标识符的规则:字母、数字、下划线,不以数字开头,注意:关键字不能作为标识符!预定义标识符有define、printf、scanf 它们是可以作为标识符的。

  • 字符可以是常数、表达式 以及 格式字符串符等。
#define Num 1000

        说明:上述代码的作用就是该程序中用Mum来替代1000,在编译预处理的时候,每当代码在源程序中遇到Mum就自动的用1000来进行代替。

        注意:宏名要简单且定义的明确,一般习惯会用大写字母来去表示,来区分和变量的区别。

🍈优点

  1. 方便程序的修改,不用对整个程序进行修改,只需对宏定义上进行修改。
  2. 提高程序的运行效率,更加方便模块化。

🍑定义宏 

        #define 机制包括了一个规则,允许把参数替换到文本当中去,这种实现操作通常被称之为是宏(macro) 或者是 定义宏(define macro)

        带参数的宏定义方式如下格式↓

#define 宏名(参数表)字符串

        那么光说是不行的,我们就用宏定义来实现两个数字的相加。代码示例如下👇

#define _CRT_SECURE_NO_WARNINGS 1
#define ADD(x,y) x+y
#include<stdio.h>
int main(void)
{printf("相加的值:%d\n",ADD(5, 5));return 0;
}

运行结果🖊 

        相加的值:10

        上述代码的意思是我们先调用宏也就是宏调用,把宏里面的值传递给宏名当中的参数表,然后再传过去的参数表替换到字符串的文本当中去。

注意:宏的参数是先完成替换的,不是先计算然后再进行传参的。如下代码所示↓

#define _CRT_SECURE_NO_WARNINGS 1
#define S(x) x*x
#include<stdio.h>
int main(void)
{printf("相加的值:%d\n",S(3+1));return 0;
}

        我一开始的时候看到这个代码以为是16,4*4不就是16吗。实际上我想错了。

        它的工作原理是这个样子的,这里3+1就是宏的参数,那么就会把3+1传递到宏的参数当中去。那么这个时候替换完成之后就是:3+1 * 3+1,这不就是7吗。没错(@^0^)

        一句话总结:参数会经过任何的计算直接传入进去。 

        实际上我们想要得到4*4的一个结果实际上这也很容易,把字符串文本修改下即可。

#define S(x) (x)*(x)

        当然这还是不够严谨,完美再加一个小括号再外面。

#define S(x) ((x)*(x))

        ()YYDS!那么这个概念性的东西就说到这里,具体还是要多上手打下代码去进行实践。 

        那么接下来我们再举出一个例子,看大家能不能做对。(╹ڡ╹ )

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define M(x) (x)+(x)
int main(void)
{printf("%d ", 10 * M(2));return 0;
}

        🍎注意⇢上述这两个代码是不一样的仔细看看哟😛

​#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define M(x) (x)+(x)
int main(void)
{int a = 2;printf("%d ", 10 * M(a));return 0;
}

        注意⇢上述这两个代码是等价的,变量也是可以传入到参数表当中去的。

选出上述代码正确的值不能 一共四个选项如下↓

A:40

B:22

C:88

D:10

        可能有些人会选择A这个选项,因为 10 * 2 = 20 然后,20+20 = 40,但实际上这是错误的和上面所犯的错误都是一模一样的。

printf("%d",10 * (2) + (2));

        原型如上代码所示↑

        那我们想要得到 40 的值就必须要加小括号。如下形式↓

#define M(x) ((x)+(x))

        其实这也无非就是操作符的优先级大小,切记(✿◕‿◕✿) 

🍈说明

        宏参数和#define的定义中可以出现其他的#define定义的变量。但是对于宏,是不能出现递归的。

        当预处理搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

在使用函数的时候我们需要注意它的数据类型,但是在宏当中我们是不需要注意的,想是整形就是整形想是浮点型就是浮点型。说明用宏在这里是更加灵活的只是处理简单问题上切记。

🍈命名事项

        相信有些小伙伴已经发现了这个函数的宏的使用语法和函数是非常类似滴。所以语言本身就会没办法帮我们区分二者的一些使用。那么我们平时写宏或者函数的时候的习惯是↓

  • 宏明全部大写形式。
  • 函数明不要全部大写,建议第一个字母大写。

🍻字符串宏常量

#include<stdio.h>
#define Name chenze
int main(void)
{printf("%s",Name);return 0;
}

(error)字符串没有带双引号编译器会直接报错✘

(correvt)正确写法是要在宏字符串带上双引号

#define Name "chenze"

        小知识点⇢宏是可以用来充当注释的效果的这个我在接触宏的时候我都没有想到这个问题,那么现在我们用BSC充当C++的风格注释。大家可以尝试去试一下这里我就不再演示了(@^0^)

🍈practice[练习]

        那么经过上述的知识点相信各位已经熟悉的差不多了接下来我们来做一道题目来练习practice以下吧。

        题目内容⇢用宏实现整形变量(a)和整形变量(b)把原来的值用宏实现清0并且打印原来(a,b)没有被宏清0之前的值。示例代码如下👇

#include<stdio.h>
#define empty0(a,b) a = 0;b = 0;
int main(void)
{int a = 20;int b = 10;printf("before:%d  %d\n", a, b);empty0(a, b);printf("after :%d  %d\n", a, b);return 0;
}

运行结果🖊

before:20  10

after   :0    0

✔说明⇢上述结果当中我们可以知道变量(a)和变量(b)通过宏被修改成为了0的值。

✔拓展⇢用do...while(0)语句结构可以在宏插入多条语句的结构因为有花括号{}在。

🍻#undef

#undef 是为取消定义,用于移除一个宏的定义。

格式形式如下

#undef NAME

如果现在的一共名字需要被重新定义的话,那么旧名字就会被移除。

🍏如下代码所示

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define NUM 10
int main(void)
{
#undef NUMprintf("num of:%d\n",NUM);
}

运行结果⇥error(错误)

        说明⇢上述代码原本是要打印NUM宏定义的值的,但是由于我们使用了#undef取消宏定义了。此时编译器就相当于未定义标识符NUM了说的简单点相当于不存在了,注:是在取消宏定义之后的语句当中的。

🍎拓展知识点⇥宏可以在任意地方使用。

#include<stdio.h>
int main(void)
{printf("num of 1:%d\n", 10);
#define M 20printf("num of 2:%d\n", M);return 0;
}

运行结果🖊

num of 1:10
num of 2:20

        🍏说明⇢在上述代码当中可以证明宏在源文件的任何地方宏都可以定义。宏的作用范围:从定义出开始往后它都是有效的。

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

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

相关文章

Docker下如何构建包含延迟插件的RabbitMQ镜像

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

OpenGLES:绘制一个彩色、旋转的3D圆柱

一.概述 上一篇博文讲解了怎么绘制一个彩色旋转的立方体 这一篇讲解怎么绘制一个彩色旋转的圆柱 圆柱的顶点创建主要基于2D圆进行扩展&#xff0c;与立方体没有相似之处 圆柱绘制的关键点就是将圆柱拆解成&#xff1a;两个Z坐标不为0的圆 一个长方形的圆柱面 绘制2D圆的…

基于Java的老年人体检管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

SNERT预备队招新CTF体验赛-Web(SWCTF)

目录 1、F12 2、robots 3、game1-喂青蛙 4、game 2 - flap bird 5、game 3 - Clash 6、Get&Post 7、sql &#xff08;1&#xff09;手工注入 &#xff08;2&#xff09;工具注入 8、命令执行漏洞 9、文件上传漏洞 10、文件泄露 11、php反序列化漏洞 12、PHP绕…

数据结构之双链表

双链表 1.复杂方法的图分析2.My_LinkedList代码3.接口MY_lIST4.测试类 1.复杂方法的图分析 2.My_LinkedList代码 package My_liNKEDlIST;public class My_LinkedList implements MY_lIST{static class ListNode{public int val;public ListNode prev;public ListNode next;pub…

Git使用【下】

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析&#xff08;3&#xff09; 目录 &#x1f449;&#x1f3fb;标签管理理解标签标签运用 …

SSM - Springboot - MyBatis-Plus 全栈体系(十七)

第三章 MyBatis 五、MyBatis 高级扩展 1. mapper 批量映射优化 1.1 需求 Mapper 配置文件很多时&#xff0c;在全局配置文件中一个一个注册太麻烦&#xff0c;希望有一个办法能够一劳永逸。 1.2 配置方式 Mybatis 允许在指定 Mapper 映射文件时&#xff0c;只指定其所在的…

函数、函数的傅里叶级数展开、傅里叶级数的和函数之间的关系

1.函数、函数的傅里叶级数展开、傅里叶级数的和函数之间的关系 1.1 傅里叶级数中的系数公式推导 我们先来推导一下傅里叶级数中的系数公式&#xff0c;其实笔者已经写过一篇相关笔记&#xff0c;详见&#xff1a;为什么要把一个函数分解成三角函数?(傅利叶级数) f ( x )…

用AI原生向量数据库Milvus Cloud 搭建一个 AI 聊天机器人

搭建聊天机器人 一切准备就绪后,就可以搭建聊天机器人了。 文档存储 机器人需要存储文档块以及使用 Towhee 提取出的文档块向量。在这个步骤中,我们需要用到 Milvus。 安装轻量版 Milvus Lite,使用以下命令运行 Milvus 服务器: (chatbot_venv) [egoebelbecker@ares milvus_…

Python中匹配模糊的字符串

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 如何使用thefuzz 库&#xff0c;它允许我们在python中进行模糊字符串匹配。 此外&#xff0c;我们将学习如何使用process 模块&#xff0c;该模块允许我们在模糊…

条件查询和数据查询

一、后端 1.controller层 package com.like.controller;import com.like.common.CommonDto; import com.like.entity.User; import com.like.service.UserService; import jakarta.annotation.Resource; import org.springframework.web.bind.annotation.GetMapping; import …

C语言 —— 函数

目录 1. 函数是什么 2. C语言中函数的分类 2.1 库函数 2.2 自定义函数 3. 函数的参数 3.1 实际参数(实参) 3.2 形式参数(形参) 4. 函数的调用 4.1 传值调用 4.2 传址调用 5. 函数的嵌套调用和链式访问 5.1 嵌套调用 5.2 链式访问 6. 函数的声明和定义 6.1函数声明…

24Hibench

1. Hibench 官网 ​ HiBench is a big data benchmark suite that helps evaluate different big data frameworks in terms of speed, throughput and system resource utilizations. It contains a set of Hadoop, Spark and streaming workloads, including Sort, WordCou…

JavaSE | 初始Java(九) | 包的使用

包 包是对类、接口等的封装机制的体现&#xff0c;是一种对类或者接口等的很好的组织方式&#xff0c;比如&#xff1a;一个包中的类不想被其他包中的类使用。包还有一个重要的作用&#xff1a;在同一个工程中允许存在相同名称的类&#xff0c;只要处在不同的包中即可。 可以…

软断言你也学不会

断言是测试用例的一部分&#xff0c;也是测试工程师开发测试用例的核心。断言通常集成在单元测试和集成测试中&#xff0c;断言分为硬断言和软断言。 硬断言是我们狭义上听到的普通断言:当用例运行后得到的[实际]结果与预期结果不匹配时&#xff0c;测试框架将停止测试执行并抛…

Python实时采集Windows CPU\MEMORY\HDD使用率

文章目录 安装psutil库在Python脚本中导入psutil库获取CPU当前使用率&#xff0c;并打印结果获取内存当前使用率&#xff0c;并打印结果获取磁盘当前使用情况&#xff0c;并打印结果推荐阅读 要通过Python实时采集Windows性能计数器的数据&#xff0c;你可以使用psutil库。psut…

AutoCAD 产品设计:图形单位

本文讲解 AutoCAD 产品的图形单位功能产品设计&#xff0c;没有任何代码实现。 使用的 AutoCAD 为 2020 版本 图形单位是什么&#xff1f; 图形单位是用于设置 一些属性数据应该用什么格式显示 的命令&#xff0c;命令标识为 un&#xff08;units&#xff09;。 举个例子。 …

WebGL笔记:绘制多个点,三角形,以及画各种不同的线条,面

绘制多点 1 &#xff09; WebGL 缓冲区 我们在用js定点位的时候&#xff0c;肯定是要建立一份顶点数据的&#xff0c;这份顶点数据是给着色器的&#xff0c;因为着色器需要这份顶点数据绘图然而&#xff0c;我们在js中建立顶点数据&#xff0c;着色器肯定是拿不到的&#xff…

基于SpringBoot的反诈宣传平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

SpringBoot注册web组件

目录 前言 一、注册Servlet组件 1.1 使用SpringBoot注解加继承HttpServet类注册 1.2 通过继承HttpServet类加配置类来进行注册 二、注册Listener组件 2.1 使用SpringBoot注解和实现ServletContextListener接口注册 2.2 ServletContextListener接口和配置类来进行注册 …