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

C语言宏定义详解

文章目录

  • 宏定义
    • 无参宏定义
    • 带参宏定义
    • 固定参数宏
    • 可变参数宏
  • 多语句宏处理
  • 连接符
  • 条件判断
  • 常见预定义宏

宏在C语言中是一段有名称的代码片段(使用#define定义),在预处理阶段会把程序中的宏名替换为对应的代码片段,然后才进入编译阶段由编译器进行编译。

  • #define:宏定义
  • #undef:取消宏定义
  • #ifdef:判断宏是否定义

宏定义

无参宏定义

最简单的宏定义时间用指定的标识符来代表代码片段,当宏定义有多行时,需要在行尾使用\来连接。

#define 宏名称  代码片段// 如(多行时,行尾使用\作为续行符)
#define BUFFER_SIZE 1024
#define RANDOM (2.0*(double)rand() / RAND_MAX)
#define NUMBERS 1, \2, \3int x[] = { NUMBERS };

带参宏定义

类似函数定义,宏名称后紧跟括号(名称与括号间不能有空格)。

固定参数宏

“形参列表”是用逗号隔开的多个标识符(也可以空,表示无参数),实参列表中的实参数量必须与宏定义中的形参数量一样多。

#define 宏名称( [形参列表] )  替换文本
// 如
#define GETCHAR() getc(stdin)
#define MAX(a,b) ((a)>(b)?(a):(b))
//参数要用括号括起,避免实参为表达式时出错,如
#define MULTIPLY(a, b) ((a)*(b))
//MULTIPLY(1+2, 3+4)会预处理为((1+2)*(3+4)),若不加括号,则会变为1+2*3+4(意义全变)。

即使加括号,宏在一定情况下还是会产生二义性(要避免此类使用),如

#define SQUARE(a) ((a)*(a))

SQUARE(a++)会预处理为((a++)(a++))(若a=3,则结果为34)。

可变参数宏

C99标准允许定义有省略号的宏(在替换文本中使用__VA_ARGS__标识可变参数),省略号必须放在参数列表的最后面表示可变参数。

#define OUTLOG(fmt, ...) printf(__func__, fmt, __VA_ARGS__)

多语句宏处理

对于有多条语句的复杂宏,为避免错误,需要使用do{}while(0)包含(避免出现多余分号等的报错)。

#define SAFE_DELETE(ptr)  \do{ \if(NULL != ptr){  \delete ptr;     \ptr=NULL;       \} \}while(0)

连接符

在宏体中,通过在参数前面加不同符号,会有不同的扩展:

  • #:参数扩展为字符串形式
  • ##:连接符,把两部分连接为一个标识符
  • #@:参数扩展为字符
    通过这些连接符,可以实现一些复杂的操作(如MFC中自动生成类等):
#define CHAR_VAR(n, c)  char var##n = #@c
#define ARRAY_VAR(n, str)  char ary##n[] = #str// char vara='a';
CHAR_VAR(a, a);
// char arya[]="abc";
ARRAY_VAR(a, abc);

条件判断

条件编译里面有判断语句,如 #if 、#else 、#elif 及 #endif。类似if语句,在里面可以使用与、或、非及比较表达式。通过条件判断可以使代码适应不同的运行环境(针对不同环境,编译不同代码部分)。

//#ifdef 是 '#if defined'的简写
#if defined(X_OS_WIN32) || defined(X_OS_WIN64) 
// Windows代码处理...
#endif

VC中判断当前是否为Debug:

#ifdef _DEBUG
#pragma comment(lib, "my-debug.lib")
#else
#pragma comment(lib, "my-release.lib")
#endif

C++中定义标准C接口(使用extern “C”)

#ifdef __cplusplus
extern "C"{
#endif// ... 代码#ifdef __cplusplus
}
#endif
在判断是否满足指定要求#if defined(MY_TEST_VER) && (MY_TEST_VER>=2)
// ...
#endif

常见预定义宏

预定义宏:

__DATE__: 字符串, 进行预处理的日期("Mmm dd yyyy", 如May 27 2006)
__TIME__: 字符串, 源文件的编译时间("hh:mm:ss",09:11:10)
__FILE__: 字符串, 代表当前源代码文件名(包含详细路径, 如F:/a.c)
__LINE__: 整数值, 代表当前源代码文件中的行号
__STDC__: 布尔值,1时表示该实现严格遵循ANSIC标准
__STDC_VERSION__: 长整型值, 表示编译器所遵循的C标准的版本号(yyyymmL,199101L)
__func__: 字符串, 当前所在函数名(C99标准)
__PRETTY_FUNCTION__: 在C中,__func__; 而在C++, 则记录了当前函数的头信息
__VA_ARGS__: 保存了可变参数列表 "…"
__cplusplus: 长整型值, 表示了C++的版本号(yyyymmL,199711L)

相关文章:

C语言宏定义详解

文章目录 宏定义无参宏定义带参宏定义固定参数宏可变参数宏 多语句宏处理连接符条件判断常见预定义宏 宏在C语言中是一段有名称的代码片段(使用#define定义),在预处理阶段会把程序中的宏名替换为对应的代码片段,然后才进入编译阶段…...

SwiftUI 动画进阶:实现行星绕圆周轨道运动

0. 概览 SwiftUI 动画对于优秀 App 可以说是布帛菽粟。利用美妙的动画我们不仅可以活跃界面元素,更可以单独打造出一整套生动有机的世界,激活无限可能。 如上图所示,我们用动画粗略实现了一个小太阳系:8大行星围绕太阳旋转,而卫星们围绕各个行星旋转。 在本篇博文中,您将…...

物理试题-空气净化器

详细解释...

Es、kibana安装教程-ES(二)

上篇文章介绍了ES负责数据存储,计算和搜索,他与传统数据库不同,是基于倒排索引来解决问题的。Kibana是es可视化工具。 分布式搜索ElasticSearch-ES(一) 一、ElasticSearch安装 官网下载地址:https://www…...

leetcode 917.仅仅反转字母

⭐️ 题目描述 🌟 leetcode链接:仅仅反转字母 ps: 这道题思路很简单,只需要一个下标在前一个下标在后,分别找是字母的字符,找到之后交换即可。 代码: class Solution { public:bool isAlpha …...

有没有推荐的golang的练手项目?

前言 下面是github上的golang项目,适合练手,可以自己选择一些项目去练习,整理不易,希望能多多点赞收藏一下!废话少说,我们直接进入正题>>> 先推荐几个教程性质的项目(用于新手学习、巩…...

springBoot的日志文件

日志是程序的重要组成部分,主要可以用来定位和排查问题。除此之外,还可以用来: 1. 记录用户的登录日志,方便分析用户是正常登录还是恶意破解; 2. 记录系统的操作日志,方便数据恢复和定位操作人;…...

Linux学习之iptables的nat表

iptables -t nat 命令 规则链 规则是格式命令。 PREROUTING一般用于内网,用于目的地址转换。 POSTROUTING一般用于外网,用于源地址转换。 iptables -t nat -A PREROUTING -i eth0 -d 114.115.116.117 -p tcp --dport 80 -j DNAT --to-destination 10.0.0…...

【数据结构】 ArrayList简介与实战

文章目录 什么是ArrayListArrayList相关说明 ArrayList使用ArrayList的构造无参构造指定顺序表初始容量利用其他 Collection 构建 ArrayListArrayList常见操作获取list有效元素个数获取和设置index位置上的元素在list的index位置插入指定元素删除指定元素删除list中index位置上…...

您的网站不应该只提供一套通用 API

后端应该提供两套 API,一套是外部使用的通用 API,服务特定的数据,另一套是自家使用的应用 API,服务特定的页面。 在当今的web开发中,构建一个提供JSON服务的后端和一个渲染应用程序的前端是很流行的。我不太喜欢&…...

vue tree禁用和多选变为单选

禁用的话和后台协调一下&#xff0c;参数中多返回一个disabled 多选变单选 在tree结构中加入一个方法 <el-treeaccordion:data"deptOptions":props"defaultProps"show-checkbox:expand-on-click-node"false":filter-node-method"filte…...

ES6新特性。对象、数组新增方法

ES6新特性 ES6&#xff08;ECMAScript 2015&#xff09;是 JavaScript 的一个重要版本&#xff0c;引入了许多新的语法和功能&#xff0c;增强了语言的表达能力和开发体验。以下是 ES6 中一些重要的新特性的全面总结&#xff1a; let 和 const 声明&#xff1a; let 和 const …...

request发送http请求

今天正式开始为大家介绍接口自动化&#xff0c;相信很多做测试的朋友&#xff0c;都用过一些工具&#xff0c;比如jmeter&#xff0c;loadrunner&#xff0c;postman等等&#xff0c;所以今天先给那些基础不太好的同学&#xff0c;先讲讲postman如何来测接口以及如何用pthon代码…...

leaflet实现MARK指向的方向随机

效果图&#xff1a; npm install leaflet-rotatedmarkerL.marker([48.8631169, 2.3708919], {rotationAngle: Math.random() * 180, // 旋转角度&#xff0c;以度为单位&#xff0c;顺时针方向。rotationOrigin: "center center", // 旋转中心 }).addTo(map);...

如何使用Python编写小游戏?

大家好&#xff0c;我是沐尘而生&#xff0c;如果你是一个热爱编程的小伙伴&#xff0c;又想尝试游戏开发&#xff0c;那么这篇文章一定能满足你的好奇心。不废话&#xff0c;让我们马上进入Python游戏开发的精彩世界吧&#xff01; Python游戏开发的魅力 编写小游戏不仅仅是锻…...

【Leetcode】84.柱状图中最大的矩形(Hard)

一、题目 1、题目描述 给定 n n n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 求在该柱状图中,能够勾勒出来的矩形的最大面积。 示例1: 输入:heights = [2,1,5,6,2,3] 输出:10 解释:最大的矩形为图中红色区域,面积为 10示例2:…...

Arraylist集合

保存数据会经常使用到数组&#xff0c;但数组存在以下几个缺陷: 长度固定&#xff1b;保存的必须为同一类型的元素&#xff0c;&#xff08;基本数据类型&#xff0c;或引用数据类型&#xff09;&#xff1b;使用数组进行增加元素的步骤比较麻烦&#xff1b; 这个时候就需要用一…...

https的原理和方案

文章目录 https原理为什么要加密常见的加密方式对称加密非对称加密数据摘要&&数据指纹数据签名 https的几种工作方案方案一&#xff1a;只使用对称加密方案二&#xff1a;只使用非对称加密方案三&#xff1a;两端都使用非对称加密方案四&#xff1a;非对称加密 对称加…...

VTK 判断一个 点 是否在一个模型 stl 内部 vtk 点是否在内部 表面 寻找最近点

判断 一个点 ,判断是否在风格 stl 模型内部&#xff0c;或表面&#xff1a; 目录 1.方案一&#xff1a;使用vtkCellLocator FindClosestPoint 找到模型上距离给定点最近的一点&#xff0c;计算两点的距离 &#xff0c;小于某一阈值 则认为此点在模型上&#xff1b; 2.方案二…...

【数据结构OJ题】链表的回文结构

原题链接&#xff1a;https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?tpId49&&tqId29370&rp1&ru/activity/oj&qru/ta/2016test/question-ranking 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 在做这道…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...