浅谈C++/C关于#define的那些奇奇怪怪的用法
前言众所周知#define(也就是宏定义)在C/C里用处很广泛。对于一个萌新小白来说宏定义有以下几种用法1 缩减代码第一种用法与typedef类似而且比typedef应用得更广泛。举个例子在以下C程序中unsigned int出现的实在是太多了。12345678910111213141516171819#includebits/stdc.husingnamespacestd;unsignedintn;intmain(){cinn;for(unsignedinti0;in;i){unsignedinta,b;cinab;while(b0){unsignedintra%b;ab;br;}coutaendl;}return0;}那该怎么办呢其实只需要加一行这样的代码然后再把unsigned int改成ui就可以了。1#define ui unsigned int这样的话程序就简短了很多。123456789101112131415161718192021#includebits/stdc.h#define ui unsigned int//也可以写作typedef unsigned int uiusingnamespacestd;ui n;intmain(){cinn;for(ui i0;in;i){ui a,b;cinab;while(b0){ui ra%b;ab;br;}coutaendl;}return0;}2 定义变量第二种用法与const auto(不一定是int)相似。当我们想写一段这样的代码时我们可以用const int写以避免重复出现10000512345678910111213#includebits/stdc.husingnamespacestd;constintN100005;inta[N],b[N],c[N],ans[N];intmain(){intn;cinn;for(inti0;in;i) cina[i]b[i]c[i];for(inti0;in;i) ans[i]a[i]b[i]-c[i];for(inti0;in;i) coutans[i] ;return0;}#define也有这个功能。它可以根据赋的“值”(不一定是值)判断改用哪种数据类型(这里就不细讲了)与auto的功能相似。因此我们也可以这样写12345678910111213#includebits/stdc.h#define N 100005//会根据后面的量以决定数据类型usingnamespacestd;inta[N],b[N],c[N],ans[N];intmain(){intn;cinn;for(inti0;in;i) cina[i]b[i]c[i];for(inti0;in;i) ans[i]a[i]b[i]-c[i];for(inti0;in;i) coutans[i] ;return0;}以下是#define的基础用法。其实#define还有一些其他功能。3 代替函数以以下程序为例在输出环节多次出现了同一行代码。那该怎么办呢123456789101112131415161718192021#includebits/stdc.husingnamespacestd;multisetints;intn,m;multisetint::iterator it,ie;intmain(){cinn;for(inti1;in;i){cinm;s.insert(m);}for(its.begin();it!s.end();it){if(it!s.begin()){if(*it!*ie) cout*it s.count(*it)endl;}elsecout*it s.count(*it)endl;ieit;}return0;}我们可以写一个输出函数。这样的话程序就变成了这个样子1234567891011121314151617181920212223#includebits/stdc.husingnamespacestd;multisetints;intn,m;multisetint::iterator it,ie;voidsc(multisetint::iterator a){cout*a s.count(*a)endl;}intmain(){cinn;for(inti1;in;i){cinm;s.insert(m);}for(its.begin();it!s.end();it){if(it!s.begin()){if(*it!*ie) sc(it);}elsesc(it);ieit;}return0;}同时我们也可以用#define对程序进行再一次优化(这是typedef做不到的)。这样的话程序代码就会大大缩减。123456789101112131415161718192021222324#includebits/stdc.h#define tor multisetint::iterator#define mi multisetintusingnamespacestd;mi s;intn,m;tor it,ie;voidsc(tor a){cout*a s.count(*a)endl;}intmain(){cinn;for(inti1;in;i){cinm;s.insert(m);}for(its.begin();it!s.end();it){if(it!s.begin()){if(*it!*ie) sc(it);}elsesc(it);ieit;}return0;}但其实输出函数那一部分也可以用#define做。可以用#define这样写输出函数1#define sc(a) cout*a s.count(*a)endl;//不需要tor,否则会报错可以发现这里的功能是不需要tor的。所以可以发现这个功能是第二个功能的衍生功能。总结一下就是#define可以代替一些简单函数。4 函数做不到的功能同时#define也可以做到一些函数做不到的功能。比如说前面这段程序还可以继续简化成这样1234567891011121314#includebits/stdc.h#define N 100005#define go(n) for(int i0;in;i)usingnamespacestd;inta[N],b[N],c[N],ans[N];intmain(){intn;cinn;go(n) cina[i]b[i]c[i];go(n) ans[i]a[i]b[i]-c[i];go(n) coutans[i] ;return0;}那这是为什么呢因为#define还可以用来代替重复出现多次的代码。运用这个方法我们可以用C语言写以下程序12345678910111213141516#includestdio.h#define N 100005#define go(n) for(int i0;in;i)inta[N],n,b[N];intmain(){scanf(%d,n);go(n)scanf(%d,a[i]);go(n){if(i0) b[i]a[i]a[n-1];elseb[i]a[i]a[i-1];printf(%d ,b[i]);}return0;}而且这个程序还能通过编译所以#define是可以套循环的。同时我们还可以用#define写一个forever(Scratch上死循环的英文)1#define forever() for(int i0;;i)或者这样写forever1#define forever(i) for(i0;;i)这样写死循环时就便利多了(话说while(10)它不香吗)。5 一些有些邪门的用法那#define既然那么好用那有没有一些邪门点的用法当然有。比如说以下这一段C语言程序就把邪门二字刻在了脑门上123456789101112#includestdio.h#define forever(i,j) for(int i0;;i)intI,love,you;voiddear(intd,ints,intx){forever(s,x) dear(d,s,x);}intmain(){scanf(%d%d%d,I,love,you);forever(love,you) dear(I,love,you);}不说递归加循环把程序卡死这变量用的也太阴间了吧这还是C语言程序(看来这才是forever的真正用法。)好了回到正题。那能不能用#define对#include进行缩减这里以下方的C程序为例。123456789101112131415161718#includebits/stdc.h#includewindows.husingnamespacestd;voidHideScreen(){HWNDhwnd;hwndFindWindow(ConsoleWindowClass,NULL);if(hwnd) ShowWindow(hwnd,SW_HIDE);return;}//千万别试intmain(){HideScreen();intxGetSystemMetrics(SM_CXSCREEN);intyGetSystemMetrics(SM_CYSCREEN);for(inti0;;i){SetCursorPos(rand()%y,rand()%x);}return0;}在这个程序中我们是否能在第二行添加#define语句来缩减#includewindows.h?很可惜这通不过编译。C/C语言的#define是不可以对带#号的指令进行宏定义的。6 与#define有关联的带“#”号指令如果你写了那么一个程序然后想把程序里的int和long long统一那该怎么办(虽然这样做对程序没有影响)是把long long全部改成int吗?可这样太麻烦了。1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950#includebits/stdc.h#define int long long#define N 100001usingnamespacestd;intm,n,ans,cnt0,sum0,li,lj,ri,rj,a[250][250];voiddg(inti,intj){if(ili) lii;if(jlj) ljj;if(iri) rii;if(jrj) rjj;ans;a[i][j]0;if(a[i][j-1]1) dg(i,j-1);if(a[i][j1]1) dg(i,j1);if(a[i-1][j]1) dg(i-1,j);if(a[i1][j]1) dg(i1,j);}voidcdr(longlongn,longlongm){memset(a,-1,sizeof(a));charc;for(longlongi1;in;i){for(longlongj1;jm;j){cinc;if(c#) a[i][j]1;}}}intmain(){cinnm;cdr(n,m);for(longlongi1;in;i){for(longlongj1;jm;j){if(a[i][j]1){lirii;ljrjj;ans0;dg(i,j);if((ri-li1)*(rj-lj1)ans) cnt;elsesum;}}}coutcntendlsum;return0;}其实你只需要在函数cdr前面加一句代码就行了1#undef int long long加上代码后话程序就变成了这样123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051#includebits/stdc.h#define int long long#define N 100001usingnamespacestd;intm,n,ans,cnt0,sum0,li,lj,ri,rj,a[250][250];voiddg(inti,intj){if(ili) lii;if(jlj) ljj;if(iri) rii;if(jrj) rjj;ans;a[i][j]0;if(a[i][j-1]1) dg(i,j-1);if(a[i][j1]1) dg(i,j1);if(a[i-1][j]1) dg(i-1,j);if(a[i1][j]1) dg(i1,j);}#undef int long longvoidcdr(longlongn,longlongm){memset(a,-1,sizeof(a));charc;for(longlongi1;in;i){for(longlongj1;jm;j){cinc;if(c#) a[i][j]1;}}}intmain(){cinnm;cdr(n,m);for(longlongi1;in;i){for(longlongj1;jm;j){if(a[i][j]1){lirii;ljrjj;ans0;dg(i,j);if((ri-li1)*(rj-lj1)ans) cnt;elsesum;}}}coutcntendlsum;return0;}这便是C/C中的#undef指令。这样的话这行代码后面的long long还是用long long表示与前面的int等价。另外C/C还有#ifdef#ifndef#elif#if#endif#if……#else#error等与宏定义有关的指令可以供您使用但入门阶段只需要知道#define就行了。

相关新闻

层次分析法实战指南:从主观决策到量化分析的科学方法

层次分析法实战指南:从主观决策到量化分析的科学方法

1. 项目概述:从拍脑袋到结构化决策在项目评审、方案选择、资源分配这些日常工作中,我们最常遇到的困境是什么?是面对一堆各有优劣的选项,感觉“公说公有理,婆说婆有理”,最后往往依赖领导的“拍板”或者团队…

2026/8/24 9:17:37 阅读更多 →
数学建模竞赛制胜心法:3小时掌握“追根溯源”高效解题工作流

数学建模竞赛制胜心法:3小时掌握“追根溯源”高效解题工作流

1. 项目概述:为什么“追根溯源”是建模竞赛的胜负手?如果你参加过哪怕一次数学建模竞赛,无论是国赛、美赛还是亚太杯,大概率都经历过这样的场景:拿到赛题后,团队陷入短暂的兴奋,紧接着就是漫长的…

2026/8/24 9:17:37 阅读更多 →
C/C++之动态内存管理方式(new delete)

C/C++之动态内存管理方式(new delete)

在C/C编程中,动态内存管理是核心能力之一,而new与delete正是实现这一功能的关键操作符。它们不仅是内存分配与释放的工具,更与对象的生命周期、资源管理深度绑定。一、new与delete的设计初衷:超越“内存分配”的对象管理C语言通过…

2026/8/24 9:17:37 阅读更多 →

最新新闻

C语言链表实现通讯录系统:数据结构课程设计实战指南

C语言链表实现通讯录系统:数据结构课程设计实战指南

1. 项目概述与核心价值通讯录系统,听起来是个老生常谈的课程设计题目,但用C语言和链表来实现,这其中的门道可一点都不少。我当年做这个设计的时候,也走过不少弯路,比如内存泄漏、链表操作混乱,导致程序动不…

2026/8/24 10:10:30 阅读更多 →
质数乘积取模:从筛法到模运算的算法实战解析

质数乘积取模:从筛法到模运算的算法实战解析

1. 问题引入:从一道看似简单的OJ题说起最近在辅导一些同学准备编程竞赛和机试时,又遇到了“东华OJ质数的乘积”这道题。题目本身描述非常简洁,通常就是给定一个正整数N,要求计算所有小于等于N的质数的乘积,并对一个较大…

2026/8/24 10:10:30 阅读更多 →
SIGMA框架:基于技能关联图的组合式多智能体系统设计

SIGMA框架:基于技能关联图的组合式多智能体系统设计

1. 项目概述:从单体智能到组合式多智能体设计的范式转变最近在跟进多智能体系统(Multi-Agent System, MAS)的前沿进展时,一个名为“SIGMA”的框架引起了我的注意。它的全称是“Skill-Incidence Graphs for Compositional Multi-Ag…

2026/8/24 10:10:30 阅读更多 →
模糊专家系统实战:从原理到工业应用与智能控制实现

模糊专家系统实战:从原理到工业应用与智能控制实现

1. 从“模糊”到“专家”:一个被误解的智能核心在人工智能的众多分支里,“模糊专家系统”这个名字听起来总有点矛盾。一方面,“模糊”似乎意味着不精确、不确定,带着点“差不多就行”的随意感;另一方面,“专…

2026/8/24 10:10:30 阅读更多 →
从质数乘积问题解析埃氏筛与高精度算法的实战应用

从质数乘积问题解析埃氏筛与高精度算法的实战应用

1. 项目概述:从一道经典OJ题看算法思维训练“东华OJ质数的乘积”这个题目,乍一看可能觉得平平无奇,不就是求几个质数的乘积吗?但如果你真的这么想,那可能就错过了这道题背后隐藏的算法思维训练价值。我在刷题和教学的过…

2026/8/24 10:10:30 阅读更多 →
不用COLMAP也能重建3D?3dgs-mcmc随机初始化模式让普通照片直达3D高斯模型

不用COLMAP也能重建3D?3dgs-mcmc随机初始化模式让普通照片直达3D高斯模型

不用COLMAP也能重建3D?3dgs-mcmc随机初始化模式让普通照片直达3D高斯模型 【免费下载链接】3dgs-mcmc [NeurIPS 2024 Spotlight] Implementation of the paper "3D Gaussian Splatting as Markov Chain Monte Carlo" 项目地址: https://gitcode.com/gh_…

2026/8/24 10:09:29 阅读更多 →

日新闻

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践 前端安全依赖分层防护。没有任何单一配置能替代输出编码、权限校验和依赖更新。 把不可信内容当作数据 默认使用框架的转义能力;确需渲染 HTML 时,先在服务端或可信的客户端库中进行白名单过滤。避免把用户输入直接赋给 inne…

2026/8/24 1:08:15 阅读更多 →
Windows登录密码存储机制全解析:从哈希算法到安全加固实战

Windows登录密码存储机制全解析:从哈希算法到安全加固实战

1. 项目概述:Windows登录密码的“黑匣子”每次你按下CtrlAltDel,输入密码,然后看到那个熟悉的桌面,这背后发生了一系列复杂而精密的操作。作为一名长期与Windows系统打交道的从业者,我经常被问到:“我的密码…

2026/8/24 1:08:15 阅读更多 →
AI面试系统安全挑战与解决方案

AI面试系统安全挑战与解决方案

1. 项目概述:AI面试系统的安全挑战去年参与某跨国企业AI面试系统部署时,遇到一个典型案例:候选人在视频面试中无意提到竞争对手产品名称,系统竟自动将该信息关联到企业知识库并生成竞品分析报告。这个看似"智能"的功能&…

2026/8/24 1:08:15 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/24 0:06:02 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/24 0:20:20 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/24 0:14:11 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/23 18:47:06 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/23 12:10:44 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/22 3:22:48 阅读更多 →