在学习 C 语言的时候,最先接触到的两个宏 MAX
和 MIN
,用于找出两个数中较大和较小的那个值。
大多数的教程中,这两个宏的定义是这样的:
#define MIN(a,b) (a) < (b) ? (a) : (b)
#define MAX(a,b) (a) > (b) ? (a) : (b)
a
和 b
可以是变量或者常量,也可以是表达式或者函数调用。
因为宏的本质是字符替换,当宏展开以后 a
或者 b
就会出现两次,也就是说如果 a
或者 b
是表达式或者函数的情况下,
就会被执行两次,可能会导致得不到预期的结果,一个简单的例子:
int a = 2, b = 1;
MAX(a++, b); // a++ 这个表达式在宏展开后,会调用两次
// a 的值变成 4
要解决这个问题也很简单,就是把 a
和 b
的结果保存起来再进行比较,在 clang 中 MAX
和 MIN
的宏定义是这样的:
#define __NSX_PASTE__(A,B) A##B
#if !defined(MIN)
#define __NSMIN_IMPL__(A,B,L) ({ __typeof__(A) __NSX_PASTE__(__a,L) = (A); __typeof__(B) __NSX_PASTE__(__b,L) = (B); (__NSX_PASTE__(__a,L) < __NSX_PASTE__(__b,L)) ? __NSX_PASTE__(__a,L) : __NSX_PASTE__(__b,L); })
#define MIN(A,B) __NSMIN_IMPL__(A,B,__COUNTER__)
#endif
#if !defined(MAX)
#define __NSMAX_IMPL__(A,B,L) ({ __typeof__(A) __NSX_PASTE__(__a,L) = (A); __typeof__(B) __NSX_PASTE__(__b,L) = (B); (__NSX_PASTE__(__a,L) < __NSX_PASTE__(__b,L)) ? __NSX_PASTE__(__b,L) : __NSX_PASTE__(__a,L); })
#define MAX(A,B) __NSMAX_IMPL__(A,B,__COUNTER__)
#endif
定义两个局部变量保存 a
和 b
的结果,然后再进行比较。
这个宏定义在 C 语言中已经完美了。
在 C++ 中,这两个宏还存在一点瑕疵,就是比较的时候 a
和 b
的结果可能不是同一种数据类型,所以在 C++ 中使用模板函数 std::min
和 std::max
来替代 MIN
和 MAX
,这两个模板函数包含在头文件 <algorithm>
中。