linux内核源码中max和min的宏实现

时间:2021-03-31 22:54:01

  今天去参加腾讯旗下互联网金融公司腾富博的初面。面试官出了这样一道题:用宏实现max,要求考虑各种非法情况。当时我回想起来《Effective C++》这本书有这方面的讨论(条款02:尽量以const,enum,inline替换#define)。可是我记得书中最后给出的方案是用模板内联函数实现的,如下:

template<class T>
inline T max(const T& x, const T& y)
{
return x > y ? x : y;
}

  所以无奈之下我想了一个折中的办法。我先给面试官写了这个max的经典的(作为反面教材<_<)宏实现:#define max(x,y) ((x)>(y)?(x):(y))。然后,我对他说这个写法是有问题的,他问我有什么问题,我就举了一个例子:max(x++,y),最后面试官点点头这个问题就过去了。不过面试完之后仔细想想这个问题,我还真没见过一种宏实现是没有问题的,所以只好求助万能的度娘,最终真找到了一个没有问题的实现(目前我看不出来有什么问题),也就是linux内核源码中的实现。

#define max(x, y) ({ \
typeof(x) _max1 = (x); \
typeof(y) _max2 = (y); \
(void)(&_max1 == &_max2); \
(_max1 > _max2 ? _max1 : _max2);})

#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
(void)(&_min1 == &_min2); \
(_min1 > _min2 ? _min1 : _min2);})

  那么我们来看一下这种实现有哪些技巧。
  首先是typeof操作符的使用,它可以计算出表达式x的类型。例如,语句int a; typeof(a) b;中的typeof(a)完全可以替换为int
  其次是语句(void)(&_min1 == &_min2);。这个语句的后半部分是一条判断语句,其实并不关心比较的结果,只是利用它进行类型检查,如果x和y的类型不一样,那么编译器会发出警告。(void)语句在这里也必不可少,如果没有这个语句,那么编译器会认为后半部分的结果没有处理,是一个无效语句,编译器会发出警告。加上(void)语句后,编译器会认为后半部分的的结果已经处理,就不会有警告发出。
  最后就是语句(_min1>_min2?_min1:_min2);。因为不需要使用xy代入三目运算符,所以就不会出现max(x++,y)x++语句可能执行两次的情况。

  本文参考链接:http://blog.sbw.so/Article/index/title/Linux 源码中对 min,max 函数的宏实现.html