#define宏定义指令
宏是可被替换的预处理记号的名字。有效的预处理记号包括有效的C++语言记号, 如标识符、字符串、数字、运算符、预处理指令、头文件名和任何单一的字符等。例如:
#define MAXLINES 500
使文本“500”(无引号)与符号MAXLINES相关联。
预处理器保存着一个由#define指令产生的所有符号的表和相应的替换文本,无论何时当预处理器在注释和带引号的字符串以外遇到符号MAXLINES时,将用“500”代替它。 需要注意的时,这只是文本替换,在编译后期的阶段它将在编译器中出现, 好像实际输入“500”来替代MAXLINES一样。在预处理期间没有语义分析。
宏定义一般可分为两种:无参数宏和带参数宏。
1.无参数宏
无参数宏就像上面的MAXLINES,有时被称为类对象宏(object-like macros),因为它通常用于定义一个类似于对象的程序常数。
无参数宏在C中用得很多, 但在C++中很少有必要使用它,应该用const代替。
例如语句:
const int MAXLINES = 500;
比下边的宏定义有很多优越性:
#define MAXLINES 500
使用const修饰符,由于编译器知道对象的语义,可以进行编译期的类型检查,也可以用符号调试器来检查const对象,const定义提供了更好的安全性。
2.带参数宏
带参数宏也称作类函数宏(function-like macros),因为使用的时候看起来很像函数。可以定义带有零个或更多个参数的带参数宏,如:
#define abs(x) ( (x) >=0 ? (x) : ((-x)) )
abs和(之前不能有空格,否则会产生展开错误.
在替换文本中应该把宏参数用括号括起来,以避免由复杂的参数表达式所引起的优先权问题。
例如,如果简单地用数学表达式定义一个宏:
#define abs(x) x >= 0 ? x : -x
则展开表达式 abs(a-1) 会得到如下结果:
a-1 >= 0 ? a-1 : -a-1
即使我们这样定义宏:
#define abs(x) ( (x) >=0 ? (x) : ((-x)) )
一般的应用看起来不会出问题,但宏调用 abs(i++) 展开后为:
( (i++) >=0 ? (i++) : (-(i++)) )
无论 i 是什么值,自增操作都将进行两次,这并不是我们所希望的。
类函数宏在C++中几乎是没有必要的, 可以使用内联函数替换绝大多数的类函数宏。例如,可以使用下边的函数替代上面的 max 宏:
inline int max( int x, int y )
{
return x >= y ? x : y;
}
这是一个真正的有作用域和类型检查的函数,不必加括号来避免优先权的争议,也无须担心像使用宏那样有其他影响,如以下调用:
max(x++, y++);
也许你会说宏的形式具有能接受任何类型参数的优势, 其实C++的函数模板同样可以解决这一问题:
template
inline T max( T x, T, y)
{
return x >= y ? x : y;
}
宏定义不是可执行的语句,无需以 ; 分号结束,额外的分号会导致出错。