Linux内核代码有很多很经典的代码,仔细去看看,可以学到很多知识。今天说说Linux是怎么实现min和max的。max和min函数都是比较常用的,可以用函数,或者利用宏去实现,一般我们会这样去写:
1 |
#define |
2 |
#define |
但是上面的写法是有副作用的。比如输入
1 |
minval |
替换宏之后,代码变成
1 |
minval |
可以看出,如果x是最小值,那么它加了两次,很明显是不对的。现在看看Linux内核是怎么实现min和max宏的。
01 |
/* |
02 |
* min()/max() macros that also do
|
03 |
* strict type-checking.. See the
|
04 |
* "unnecessary" pointer comparison.
|
05 |
*/
|
06 |
#define min(x, y) ({ \
|
07 |
typeof(x) _min1 = (x); \
|
08 |
typeof(y) _min2 = (y); \
|
09 |
( void ) (&_min1 == &_min2); \
|
10 |
_min1 < _min2 ? _min1 : _min2; })
|
11 |
|
12 |
#define max(x, y) ({ \
|
13 |
typeof(x) _max1 = (x); \
|
14 |
typeof(y) _max2 = (y); \
|
15 |
( void ) (&_max1 == &_max2); \
|
16 |
_max1 > _max2 ? _max1 : _max2; })
|
17 |
|
18 |
#define min3(x, y, z) ({ \
|
19 |
typeof(x) _min1 = (x); \
|
20 |
typeof(y) _min2 = (y); \
|
21 |
typeof(z) _min3 = (z); \
|
22 |
( void ) (&_min1 == &_min2); \
|
23 |
( void ) (&_min1 == &_min3); \
|
24 |
_min1 < _min2 ? (_min1 < _min3 ? _min1 : _min3) : \
|
25 |
(_min2 < _min3 ? _min2 : _min3); })
|
26 |
|
27 |
#define max3(x, y, z) ({ \
|
28 |
typeof(x) _max1 = (x); \
|
29 |
typeof(y) _max2 = (y); \
|
30 |
typeof(z) _max3 = (z); \
|
31 |
( void ) (&_max1 == &_max2); \
|
32 |
( void ) (&_max1 == &_max3); \
|
33 |
_max1 > _max2 ? (_max1 > _max3 ? _max1 : _max3) : \
|
34 |
(_max2 > _max3 ? _max2 : _max3); })
|
里面有很多东西都没见过,但是它能解决传统的min/max宏带来的副作用。下面来一一说一下上面宏的含义:
- typeof(xxx)含义。
typeof(xxx)的含义是用来获取xxx的类型,比如上面的1
typeof(x)
_min1 = (x);typeof(x)是获得x的类型,上面的含义相当于
1
int
_min1 = (x);
- ({XXXX})含义。
({XXXX})类似与C中的逗号表达式,XXXX可以包含有多条语句(可以是变量定义、复杂的控制语句),该表达式的值为XXXX中的最后一条语句的值。比如下面01
#include
<iostream>02
03
using
namespace
std;
04
05
int
main(){
06
int
lastValue = 0;
07
lastValue = ({
08
int
x = 1, y = 10;
09
for
(
int
i = 1; i <= y; i++){
10
x *= i;
11
}
12
x;
13
});
14
15
cout << lastValue << endl;
16
return
0;
17
}
结果是10的阶乘值。
结合了type和({})可以很好的消除宏的副作用。比如上面的
1 |
minval |
如果代入了Linux内核中的min宏,扩展之后会变成:
1 |
minval |
2 |
typeof(x) _min1 = (x++); \
|
3 |
typeof(y) _min2 = (y); \
|
4 |
( void ) (&_min1 == &_min2); \
|
5 |
_min1 < _min2 ? _min1 : _min2; })
|
可以看到,x只被加了一次,如果x是最小值,结果是正确的。
本博客文章除特别声明,全部都是原创!尊重原创,转载请注明: 转载自过往记忆(http://www.iteblog.com/)
本文链接地址: 《Linux内核中是怎么实现min和max函数》(http://www.iteblog.com/archives/237)