#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
为什么不简单地
(a>b ? a : b)
?
因为否则
max(f(1), f(2))
会调用两个函数之一两次:
f(1) > f(2) ? f(1) : f(2)
而是通过“缓存”
_a
和 _b
中的两个值,您就拥有了
({
sometype _a = (a);
sometype _b = (b);
_a > _b ? _a : _b;
})
(正如其他人明确指出的那样,自动增量/自动减量也存在同样的问题)
我认为 Visual Studio 不支持这种方式。这是一个复合语句。请阅读此处 msvc 是否有 gcc 的 ({ }) 类似功能
我将补充一点,此处给出的 gcc 手册中复合语句的定义 http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC62 显示了与该代码非常相似的代码max 的问题:-)
它解决了以下主要问题:
#define max(a,b) ((a) > (b) ? a : b)
当您使用具有副作用的表达式来调用它时,超出了对值的简单评估,事情可能不会按照您的想法行事。考虑代码:
int x = max (a++, b--);
由于宏是简单的文本替换,因此会产生以下翻译:
int x = ((a++) > (b--) ? a++ : b--);
这几乎肯定不是您想要的,因为它会增加 a
或减少
b
两次,具体取决于它们的相对值。但是,请考虑一下如果我们改为使用以下效果:
#define max(a,b) ({ \
typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; \
})
在这种情况下,它使用临时变量,有效地转换为:
int x = ({ int _a = a++; int _b = b--; _a > _b ? _a : _b; })
这只会运行副作用一次。
但是,说实话,您应该完全放弃该宏并使用
inline
函数,甚至是非内联函数,因为大多数时候,即使没有
该建议,编译器也可以完成不错的优化工作.早期 C 中宏的两个用例是类似函数的宏(例如您问题中的宏)和定义相关用途的常量。 前者最好使用内联函数
(1)
处理,后者则使用枚举。如今,我将宏的使用限制为非常简单的定义。(1)
inline
是一个建议,而类似函数的宏保证是内联的。但是,我发现编译器通常可以更好地确定是否遵循该建议(而不是开发人员)。
确定最大值的另一种方法(至少对于正数)
由于 a 和 b 仅访问一次,因此 MAX(a++,b++) 给出正确的结果。
如果使用表达式调用宏,可能会导致意外行为。假设这个:
int c = max(i++, j++);
在这种情况下,简单版本的最大值增加两倍。