C/C++高级特性之——预处理器中的宏(Macro)#define 详解
宏(英语:Macro)是一种批量处理的称谓。
计算机科学里的宏是一种抽象(Abstraction),它根据一系列预定义的规则替换一定的文本模式。解释器或编译器在遇到宏时会自动进行这一模式替换。对于编译语言,宏展开在编译时发生,进行宏展开的工具常被称为宏展开器。
宏这一术语也常常被用于许多类似的环境中,它们是源自宏展开的概念,这包括键盘宏和宏语言。绝大多数情况下,“宏”这个词的使用暗示着将小命令或动作转化为一系列指令。
——摘自:百度百科
得,估计这段东西也没人要看,那我们就进入正题吧。
欢迎关注我的公众号:Huayu_IT!里面有许多编程和计算机的有趣知识哦~
目录
本文为EricNTH的原创博客,转载请注明出处!
宏
宏的定义
在最顶上,不看也罢。
C++中宏的用途
1.定义常量
语法
#define CONSTANT_NAME CONSTANT_VALUE
举个例子:
#define PI 3.1415926
替代方案
const double PI = 3.1415926
两种方法的利弊:
使用宏#define:使用方便快捷,且有许多方法。但是不是类型安全的。
使用const:语法比较长,但是类型安全。
可以自行挑选。
补充内容
你可以使用 #ifdef
(#if defined) 或 #ifndef
(#if not defined) 来检查常量是否有被定义。
你可以使用#undef
来解除对一个常量的定义。
例如:
#ifdef PI
//do sth.
#endif
#ifndef PI
//do sth.
#endif
#undef PI //PI is not defined since then!
以上内容仅适用于#define宏,不适用于const。
2.多重包含防范
语法&示例
#ifndef MAIN_H
#define MAIN_H
#endif
用途
保证一个头文件不被多次包含,如例子中是main.h
的方法,一般宏名起作文件名的大写,.等符号用_替换。
替代方案
#pragma once
这样与上面效果完全相同,而且比上面简介,不容易错。
推荐后者。
3.创建宏函数
语法
#define FUNCTION_NAME(PARAMETER LIST) somefunctions();\
otherfunctions();
宏函数,是宏中难度较高的一部分了。
不太容易理解,而且很容易犯错。
下面就让我给大家讲一讲它的各种内容。
示例
#define MAX_THREE(a,b,c) (((a)>(b) ? \
((a)>(c)?:(a):(c)):\
((b)>(c)?:(b):(c))))
如果调用它(如:cout << MAX_THREE(1,x,2+3 << endl;
),实际上编译器是进行了如下的操作:
cout << (((1)>(x)?((1)>(2+3)?:(1):(2+3)):((x)>(2+3)?:(x):(2+3)))) << endl;
其实我故意写麻烦了(其实直接
max(a,max(b,c))
就可以了,我这样写就是因为有东西要和大家讲。
顺便说一句,?:是条件三目运算符,不懂可以自行百度。
思路大家应该大家应该都能了解,主要我们来看一下里面的语法。
语法&注意事项
(1) \
:宏函数可以通过\
来扩展到下一行,最后一行不用加。适当使用\
可以增强代码的可读性。
(2)MAX_THREE
:宏的命名(按照惯例)应该全部大写,单词之间应该用下划线分隔开。宏名应该需要具有自我描述性。
(3)MAX_THREE(a,b,c)
:在形参与宏名这边一定不!要!加!空!格!!!否则99.99%出错!(否则编译器会识别为常量等,导致错乱)
(4)(a)(b)(c)
:在宏中使用参数时,两边一定要加括号!当传入的参数是一个数或变量时还好,若传入的是一个表达式,则在展开时会发生重大问题!
(5)整个表达式两边也要加括号!
替代方案
宏函数,最好的替代方案是模板(最新的ANSI C++标准全面支持),可以参见我的这篇Blog>>>
字符串化与字符串拼接(宏函数特有功能)
大家猜一猜,这些代码会输出什么结果?
#define PRINT(x) cout << #x << " = " << x << endl;
double num = 7.5;
PRINT(num);
答案在评论区哦!
#
运算符可以将它后面跟着的那个东西字符串化。
还有拼接##
运算符,和#
是差不多的哟!我的这篇文章里面(在中间)有说明。
为什么不建议用宏
最重要的一点是:Macro不是类型安全的,这严重破坏了C++的强类型特征。
然后,宏不会出现在编译器生成的中间源代码中(它在编译初期预处理阶段就已经被替换掉了),因此难以调试。
而且,虽然简便,但大型宏非常难以管理(虽然可以用\
扩展到下一行)。
最后,也并不重要,宏是C风格,不是C++风格。
建议大家看一下我的这篇博客,,里面也进行了说明。
为什么要保留宏
既然C++中宏的每个用途都有更好的替代方案,为什么还要保留它呢?
1.也是最重要的,C语言中宏是非常常用的,如宏函数等更是不可替代的(当时,模板是C++特性),而C++必须向后兼容C的全部特性。
2.有些方面,虽然替代方案更好,但可能宏更简短。
3.宏函数中字符串拼接,与字符串化等特性,只有宏支持,其它(模板函数)并不支持。
好了今天就讲到这里,谢谢大家!
本文为EricNTH的原创博客,转载请注明出处!