Defining function-like macros 定义类函数宏命令

类函数宏命令非常强大,但也会引起很多麻烦,完全取决于你是怎么用它。它的创建方法和类对象宏命令一样,但是你可以给它们传参数,并且在宏命令内部使用这些参数。

你要直接宏命令名称后接一对圆括号,括号里写参数名,名称和括号之间不能有括号。

我们来看下面这个例子:

#define MINVAL(x, y) x < y ? x : y

这个例子里创建了一个类函数宏命令,它有两个参数,返回两个参数里较小的一个。

NSInteger minimum = MINVAL(1, 2);
NSLog(@"The lower number is %ld", (long)minimum);

预处理器处理这段代码的背后是这样的:

NSInteger minimum = 1 < 2 ? 1 : 2
NSLog(@"The lower number is %ld", (long)minimum);

这段代码单独运行没问题,但是如果像下面这么写的话,返回的结果会是 1:

NSInteger minimum = 1 + MINVAL(1, 5);

为什么嘞?

因为它展开之后是这样的:

NSInteger minimum = 1 + 1 < 5 ? 1 : 5

根据运算符,它的意思其实是:「 如果 1 + 1 的值比五要小的话,就返回 1 + 1的值,否则返回 5」。然而我们的目的不是这样的。

好在 Objective-C 自己就有 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

类函数宏命令的好处在于不用调用函数了,但是讲老实话就是,调用函数其实超方便的……所以请不要轻易「优化」你的代码,真的没啥必要。

有两个比较常用的类函数宏命令,DEG2RAD() 和 RAD2DEG(),你可能会在数学转换计算里面用到:

#define DEG2RAD(x) ((x) * M_PI / 180.0f)
#define RAD2DEG(x) ((x) * 180.0f / M_PI)

注意,这个 X 用括号锁起来了,这是为了防止别的运算符干扰它。

results matching ""

    No results matching ""