该min
函数的经典预处理器版本看起来像
#define min(a, b) ((a) < (b) ? (a) : (b))
这使你可以进行双重评估 - 你做的情况min(f(), g())
,忘记f
或g
有副作用,你必须花费数小时试图找出你的功能运行两次的原因.为了防止这种情况,你可以做到
#define min(a, b) ({__typeof__(a) _a = (a); \ __typeof__(b) _b = (b); \ _a < _b ? _a : _b;})
这在GCC下运行得很好,但是如果你通过-Wgnu
套装运行它- 这套警告属于-pedantic
你的保护范围内- 你得到的错误就像
test.c:5:10: error: use of GNU statement expression extension [-Werror,-Wgnu] int a = min(3, 7); ^ test.c:1:22: note: expanded from macro 'min' # define min(a, b) ({__typeof__(a) _a = (a); __typeof__(b) _b = (b); _a < _b ? _a : _b;})
是否有可能以防止双重评估的方式定义这些宏,并且 Clang可以接受哪些宏-pedantic
?(是的,您可以禁用警告-Wno-gnu
,在这种情况下,Clang处理语句表达没有问题.我问,因为我,因为我clang -pedantic
太自负了.)
编辑:我在C工作.我也标记了这个C++,因为我认为解决方案可能适用于C++以及C.哎呀 - 忘了模板!抱歉模棱两可.
如果你真的用C++编写,那么就不要使用预处理器:
template <typename T> const T min(const T& a, const T& b) { return (b < a) ? b : a; }
(请注意,我换b
和a
,让你得到左手操作,如果两者相等).
否则不,不是真的.
我认为这可以作为C11解决方案.
inline int min(int const x, int const y) { return y < x ? y : x; } inline unsigned minu(unsigned const x, unsigned const y) { return y < x ? y : x; } inline long minl(long const x, long const y) { return y < x ? y : x; } inline unsigned long minul(unsigned long const x, unsigned long const y) { return y < x ? y : x; } inline long long minll(long long const x, long long const y) { return y < x ? y : x; } inline unsigned long long minull(unsigned long long const x, unsigned long long const y) { return y < x ? y : x; } inline float minf(float const x, float const y) { return y < x ? y : x; } inline double mind(double const x, double const y) { return y < x ? y : x; } inline long double minld(long double const x, long double const y) { return y < x ? y : x; } #define MIN(X, Y) (_Generic((X) + (Y), \ int: min, \ unsigned: minu, \ long: minl, \ unsigned long: minul, \ long long: minll, \ unsigned long long: minull, \ float: minf, \ double: mind, \ long double: minld)((X), (Y)))