宏定义——一种信息学竞赛中优化代码结构的工具
引言
信息学竞赛的初学者总是容易犯一些低级错误——忘记文件 IO,忘记删调试信息,变量名、函数名冲突等。同时,当竞赛选手需要写部分分或遇到一些特殊情况(比如程序需要根据不同的数据范围选择不同的计算方案)时,也需要一些工具优化代码的组织结构。这时,宏定义便成为了有效的工具。
正文
使用
宏定义是 C 语言和 C++ 中的一种预处理指令,允许程序员在源代码中定义一个标识符,以便在后续的代码中用该标识符代替特定的值或代码块。宏定义在代码编译之前会被预处理器进行处理,其作用类似于进行代码替换,有助于提高代码的可读性和可维护性。它的用法时这样的:
#define <宏名>(参数) <字符串>
例如,#define int long long
能够在编译时将 int
字符串替换为 long long
。
常见与其配合使用的还有这些语句:
语句 | 含义 |
---|---|
#ifdef <宏名> |
检查宏是否被定义 |
#ifndef <宏名> |
检查宏是否没有被定义 |
#endif |
作为ifdef 和ifndef 的结束标志 |
#else |
作为ifdef 和ifndef 的否定 |
#undef <宏名> |
取消宏定义 |
也就是说,宏定义会对代码中的表示符进行“替换”。下面是一个使用宏定义编写 A+B 问题代码的例子:
#include <iostream> #define int long long // 宏定义 int int a, b, c; // 此处将按照 long long 编译 #ifdef int #undef int // 宏定义 int 结束 #endif #define ADD(x,y) x+y // 宏定义 ADD int main() { // 此处将按照 int 编译 #ifndef ONLINE_JUDGE // 如果编译时使用了 -DONLINE_JUDGE 则不会使用文件读写 freopen("aplusb.in", "r", stdin); freopen("aplusb.out", "w", stdout); #endif std::cin >> a >> b; c = ADD(a,b); // 此处将按照 a+b 编译 std::cout << c << std::endl; return 0; }
由此可见,宏定义能够辅助编写代码,并降低因忘记文件读写等问题导致丢分的概率。善用宏定义能够在大型考试中快速调试代码,并解决一些常规方法不易解决的问题。
注意事项
- 运算优先级。例如,如果定义
pf(x)
为x*x
,则pf(a+b)
将被替换为a+b*a+b
,可能不符合预期,因此可能需要适当加入括号调整运算优先级。例如,如果想让替换结果变为(a+b)*(a+b)
,定义可能需要写成#define pf(x) (x)*(x)
。 - 传参的计算次数。例如,如果定义
#define ABS(x) (x>0)?x:-x
,则ABS((pd()))
将会被替换为((pd())>0) ? (pd()) : -(pd())
,导致pd
被执行 次。如果pd
的运算结果变化则会出错,而且程序运行时间也会大大加长。
致谢
感谢 tristiano 对文章编写的帮助。
本文来自博客园,作者:cwkapn,转载请注明原文链接:https://www.cnblogs.com/chenaknoip/p/18729871
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了