当前位置: 首页 > news >正文

【C语言基础】宏定义的用法详解

📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨
📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】
📢:文章若有幸对你有帮助,可点赞 👍 收藏 ⭐不迷路🙉
📢:内容若有错误,敬请留言 📝指正!原创文,转载请注明出处

文章目录

  • 引言:为什么使用宏定义?
  • 一、宏定义的定义
    • 1. 简单宏定义:
    • 2. 参数化宏定义:
    • 3. 字符串化宏定义:
    • 4. 连接宏定义:
    • 5. 条件宏定义:
    • 6.宏定义嵌套宏定义:
  • 二、宏定义需要注意的问题
  • 三、宏定义中为什么要加do和while(0)?


引言:为什么使用宏定义?

C语言中,一般都不会直接使用常量,而是先将其定义为一个宏,然后在程序中使用该宏名,进而调用了这个常量。
好处:修改方便。等我们需要修改这个常数时候,只需要在宏定义出修改一次即可。而不用到代码中到处去寻找,看哪里都用过这个常数。

一、宏定义的定义

在C语言中,宏定义是一种预处理指令,用于在编译之前将标识符替换为特定的值或代码片段。下面是几种常见的宏定义方式:

1. 简单宏定义:

#define 宏名 值

示例:

#define PI 3.14159
#define N (321)

定义N等于321。N在使用过程中会被321完全代替。注意不需要加“;”。其次,赋值的数值最好加上小括号。

2. 参数化宏定义:

#define 宏名(参数列表) 值或代码片段

示例:

#define MAX(a, b) ((a) > (b) ? (a) : (b))

3. 字符串化宏定义:

#define STRINGIFY(x) #x

示例:

printf("宏名: %s\n", STRINGIFY(MAX));
// 输出: 宏名: MAX

4. 连接宏定义:

#define CONCAT(a, b) a##b

示例:

int CONCAT(a, b) = 10;
// 相当于 int ab = 10;

5. 条件宏定义:

#ifdef 宏名
#ifndef 宏名
#endif

示例:

#define DEBUG
#ifdef DEBUGprintf("调试模式\n");
#endif

这些是C语言中常见的宏定义方式,使用宏定义可以在代码中提供一定的灵活性和可定制性。需要注意的是,宏定义是简单的文本替换,使用时需谨慎避免潜在的副作用和命名冲突。

6.宏定义嵌套宏定义:

#define M (N+5)
#define S(r) (PI*r*r)

宏定义的分类:对象宏和函数宏(函数宏顾名思义,就是行为类似函数)
例如:

#define a 3.14
#define N (a*a)

二、宏定义需要注意的问题

1.宏定义一般在函数的外面。
2.宏定义必须要先定义,再使用宏。如果先使用就会编译报错。
3.宏定义中宏名一般使用大写,便于区分变量名。不是语法规定的,是一般约定俗成的。

三、宏定义中为什么要加do和while(0)?

目的:在宏定义中添加do{...}while(0)结构的目的是为了将多个语句作为宏的一个整体,使其在代码中的使用更加灵活和安全。

宏展开后的代码会替代宏的调用部分,如果不使用do{...}while(0)结构,而是直接用花括号{...}包裹展开的代码,可能会导致在某些场景下产生语法错误或意想不到的行为。
下面是一些理由解释为什么要使用do{...}while(0)结构:

1.语法问题:do{...}while(0)结构保证了展开的代码作为一个完整的语句块存在。如果不添加这样的结构,并且将展开的代码用花括号包裹,可能会在某些情况下引起语法错误。使用do{...}while(0)结构能够确保展开的代码符合语法要求。

2.宏的调用位置:在一些特定的上下文中,宏的调用可能需要像普通的语句一样出现。例如,将宏用作函数调用的参数,或者将多个宏调用放在一个复合语句的条件部分。使用do{...}while(0)结构可以让宏的展开代码在这些情况下保持一致的行为。

3.语句的结束符号:由于宏展开后生成的代码可能包含多个语句,因此在每个语句的末尾都需要添加结束符号。使用do{...}while(0)结构可以确保在每个语句之后都添加了;分号,以避免语法错误。

总之,使用do{...}while(0)结构可以确保宏展开后的代码在各种上下文中具有一致的行为,避免语法错误,并且能够被作为单个语句来使用。这是一种常见的宏定义的惯用写法。

在这里插入图片描述

相关文章:

【C语言基础】宏定义的用法详解

📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...

微服务系列文章之 SpringBoot 最佳实践

Spring Boot 是一种广泛使用且非常流行的企业级高性能框架。 以下是一些最佳实践和一些技巧,我们可以使用它们来改进 Spring Boot 应用程序并使其更加高效。 Spring Boot 的四大核心 1、自动配置 针对很多Spring应用程序和常见的应用功能,Spring Boo…...

C++并发多线程--std::async、std::packaged_task和std::promise的使用

目录 1--std::async的使用 2--std::packaged_task的使用 3--std::promise的使用 1--std::async的使用 std::async用于启动一个异步任务,并返回一个std::future对象;std::future对象里含有异步任务线程入口函数的结果; std::launch::deferr…...

opencv-目标追踪

import argparse import time import cv2 import numpy as np# 配置参数 ap argparse.ArgumentParser() ap.add_argument("-v", "--video", typestr,help"path to input video file") ap.add_argument("-t", "--tracker", …...

【数据结构】 单链表面试题讲解

文章目录 引言反转单链表题目描述示例:题解思路代码实现: 移除链表元素题目描述:示例思路解析: 链表的中间结点题目描述:示例:思路解析代码实现如下: 链表中倒数第k个结点题目描述示例思路解析&…...

C++ string类的模拟实现

模拟实现string类不是为了造一个更好的轮子,而是更加理解string类,从而来掌握string类的使用 string类的接口设计繁多,故而不会全部涵盖到,但是核心的会模拟实现 库中string类是封装在std的命名空间中的,所以在模拟…...

Qt实现简单的漫游器

文章目录 Qt的OpenGL窗口GLSL的实现摄像机类的实现简单的漫游器 Qt的OpenGL窗口 Qt主要是使用QOpenGLWidget来实现opengl的功能。  QOpenGLWidget 提供了三个便捷的虚函数,可以重载,用来重新实现典型的OpenGL任务: paintGL:渲染…...

【c语言】文件操作

朋友们,大家好,今天分享给大家的是文件操作的相关知识,跟着我一起学习吧!! 🎈什么是文件 磁盘上的文件是文件。 但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件 程序文…...

【Unity】坐标转换经纬度方法(应用篇)

【Unity】坐标转换经纬度方法(应用篇) 解决地图中经纬度坐标转换与unity坐标互转的问题。使用线性变换的方法,理论上可以解决小范围内所以坐标转换的问题。 之前有写过[Unity]坐标转换经纬度方法(原理篇),在实际使用中&#xff0c…...

element时间选择器el-date-picter使用disabledDate指定禁用的日期

需要的效果 <el-date-pickerclass"selectstyle"v-model"year"value-format"yyyy"type"year":picker-options"disabledCli"placeholder"选择年"> </el-date-picker>data() {return {disabledCli: {/…...

出学校干了 5 年外包,已经废了

如果不是女朋友和我提分手&#xff0c;我估计现在还没醒悟 本科大专&#xff0c;17年通过校招进入某软件公司做测试&#xff0c;干了接近5年的功能。 今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01;而我已经…...

day-23 代码随想录算法训练营(19)part09

669.修剪二叉搜索树 思路一&#xff1a;根据二叉搜索树的特性进行中间值与去区间值判断&#xff0c;有三种情况&#xff1a;1.在区间中&#xff0c;所以左右子树都可能在区间中&#xff1b; 2.在区间外面的左侧&#xff0c;必然只有右子树可能存在区间中&#xff1b;3.在区间外…...

JVM编译优化

即时编译器 HotSpot虚拟机中内置了两个即时编译器,分别称为Client Compiler和Server Compiler,或者简称为C1编译器和C2编译器。Java8默认开启Server模式。用户可以使用“-client”或“-server”参数去指定编译模式。 C1编译器启动速度快,关注局部简单可靠的优化,比如方法…...

vue浏览器插件安装-各种问题

方法1&#xff1a;vue.js devtolls插件下载 https://blog.csdn.net/qq_55640378/article/details/131553642 下载地址&#xff1a; Tags vuejs/devtools GitHub npm install 或是 cnpm install 遇到的报错 设置淘宝镜像源&#xff08;推荐使用nrm&#xff0c;这一步是为…...

maven工具-maven的使用-镜像仓库、本地仓、IDEA使用maven

Maven 一、为什么使用maven 添加第三方jar包jar包之间的依赖关系处理jar包之间的冲突获取第三方jar包将项目拆分成多个工程模块实现项目的分布式部署 二、maven简介 ​ Maven项目对象模型(POM)&#xff0c;可以通过一小段描述信息来管理项目的构建&#xff0c;报告和文档的…...

Mac鼠标增强工具Smooze Pro

Smooze Pro是一款Mac上的鼠标手势增强工具&#xff0c;可以让用户使用鼠标手势来控制应用程序和系统功能。 它支持多种手势操作&#xff0c;包括单指、双指、三指和四指手势&#xff0c;并且可以自定义每种手势的功能。例如&#xff0c;您可以使用单指向下滑动手势来启动Expos视…...

数据结构-单链表(C语言简单实现)

简介 以顺序结构进行数据存储时&#xff0c;它的特点就是可以用一组任意的存储单元存储数据元素&#xff0c;这组存储单元可以是连续的&#xff0c;也可以是不连续的&#xff0c;这些数据可以存在内存未被占用的任意位置。它也是有缺点的&#xff0c;就是在插入和删除时需要移…...

.netcore grpc身份验证和授权

一、鉴权和授权&#xff08;grpc专栏结束后会开启鉴权授权专栏欢迎大家关注&#xff09; 权限认证这里使用IdentityServer4配合JWT进行认证通过AddAuthentication和AddAuthorization方法进行鉴权授权注入&#xff1b;通过UseAuthentication和UseAuthorization启用鉴权授权增加…...

分布式 - 服务器Nginx:一小时入门系列之负载均衡

文章目录 1. 负载均衡2. 负载均衡策略1. 轮询策略2. 最小连接策略3. IP 哈希策略4. 哈希策略5. 加权轮询策略 1. 负载均衡 跨多个应用程序实例的负载平衡是一种常用技术&#xff0c;用于优化资源利用率、最大化吞吐量、减少延迟和确保容错配置。‎使用 nginx 作为非常有效的HT…...

Linux学习之基本指令二

-----紧接上文 在了解cat指令之前&#xff0c;我们首先要了解到Linux下一切皆文件&#xff0c;在学习c语言时我们就已经了解到了 对文件输入以及读入的操作&#xff08;向显示器打印&#xff0c;从键盘读取数据&#xff09;&#xff0c;对于Linux下文件的操作&#xff0c;也是…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

【SpringBoot自动化部署】

SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一&#xff0c;能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时&#xff0c;需要添加Git仓库地址和凭证&#xff0c;设置构建触发器&#xff08;如GitHub…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...

C++ Saucer 编写Windows桌面应用

文章目录 一、背景二、Saucer 简介核心特性典型应用场景 三、生成自己的项目四、以Win32项目方式构建Win32项目禁用最大化按钮 五、总结 一、背景 使用Saucer框架&#xff0c;开发Windows桌面应用&#xff0c;把一个html页面作为GUI设计放到Saucer里&#xff0c;隐藏掉运行时弹…...

Clickhouse统计指定表中各字段的空值、空字符串或零值比例

下面是一段Clickhouse SQL代码&#xff0c;用于统计指定数据库中多张表的字段空值情况。代码通过动态生成查询语句实现自动化统计&#xff0c;处理逻辑如下&#xff1a; 从系统表获取指定数据库&#xff08;替换your_database&#xff09;中所有表的字段元数据根据字段类型动态…...

matlab实现DBR激光器计算

DBR激光器计算程序。非常值得参考的程序。DBR激光器程序 DBR计算/1.txt , 2056 DBR计算/4.asv , 22 DBR计算/4.txt , 32 DBR计算/GetDeviceEfficiency.asv , 2012 DBR计算/GetDeviceEfficiency.m , 2014 DBR计算/GetOneLayerArray.asv , 837 DBR计算/GetOneLayerArray.m , 836…...