Linux内核源码--min,swap宏定义

Linux3.5的部分宏定义在Linux-3.5/include/linux/kernel.h的头文件中有定义

一: 最大值和最小值相关的宏


[cpp]  view plain  copy
  1. /* 
  2.  * min()/max()/clamp() macros that also do 
  3.  * strict type-checking.. See the 
  4.  * "unnecessary" pointer comparison. 
  5.  */  
  6. #define min(x, y) ({                \  
  7.     typeof(x) _min1 = (x);          \  
  8.     typeof(y) _min2 = (y);          \  
  9.     (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); })  

以上几个宏会做严格的类型检查

(void) (&_min1 == &_min2); 

表面看起来,这句话,好像不起作用,算是一句废话,其实作用还是比较大的。首先,我们此处想要实现的目的是,在计算两个数的最小值之前,希望去判断一下两个值的类型是否一致,而由于C语言本身不支持我们去做类似于这样的操作typeof(_x)==typeof(_y),所以在此,通过故意判断他们2个的地址指针是否相等,而显然&_x,即x的地址,是不可能等于&_y的,但是这句话(void) (&_x == &_y);使得,如果_x和_y的类型不一样,其指针类型也会不一样,2个不一样的指针类型进行比较操作,则会引起编译器产生一个编译警告,提示你这两个值的类型不同通过void显式丢弃一个表达式的值,否则有些编译器会就此给出警告信息。 


比如看看如下代码:


编译的时候,经过预处理后,就会有这样的判断操作:

int * == char *;

因此编译器就会提示你:

warning: comparison of distinct pointer types lacks a cast(警告:比较不相关的指针时缺少类型转换)

所以,这个宏的巧妙之处就在于此。

所以,总结起来就是:

【提示】

1。其实关于min的宏,更好的做法是再加个const,即:

[cpp]  view plain  copy
  1. #define min(x, y) ({                        \  
  2.     const typeof(x) _min1 = (x);            \  
  3.     const typeof(y) _min2 = (y);            \  
  4.     (void) (&_min1 == &_min2);              \  
  5.     _min1 < _min2 ? _min1 : _min2; })  


2。(void) (&_x == &_y); 中的void,表示将表达式(&_x == &_y); 所得到的结果(此处肯定是逻辑上的假,值为0)忽略掉。如果不加void,则会提示你这行代码是无意义的,没人用到,有些编译器会产生警告信息


3。关于min的宏定义,为何这么复杂,而不是用简单的#define min(x,y) ((x) < (y) ? x : y)

因为,如果如此定义,那么对于一些特殊的值传入此宏之后,就会产生一些副作用,产生的结果,就不是我们想要的了,比如:

min(++a,++b) ==> ((++a)<(++b))?(++a) : (++b) 

就使得,a++和b++分别执行了2次,而且min的结果,也不对了。而用上面那个复杂的定义,多加了局部变量_x和_y,就可以避免此类问题了。


二、 其它相关宏的分析

[cpp]  view plain  copy
  1. /** 
  2.  * min_not_zero - return the minimum that is _not_ zero, unless both are zero 
  3.  * @x: value1 
  4.  * @y: value2 
  5.  */  
  6. #define min_not_zero(x, y) ({           \  
  7.     typeof(x) __x = (x);            \  
  8.     typeof(y) __y = (y);            \  
  9.     __x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); })  
  10.   
  11. /* 
  12.  * ..and if you can't take the strict 
  13.  * types, you can specify one yourself. 
  14.  * 
  15.  * Or not use min/max/clamp at all, of course. 
  16.  */  
  17. #define min_t(type, x, y) ({            \  
  18.     type __min1 = (x);          \  
  19.     type __min2 = (y);          \  
  20.     __min1 < __min2 ? __min1: __min2; })  
  21.   
  22. #define max_t(type, x, y) ({            \  
  23.     type __max1 = (x);          \  
  24.     type __max2 = (y);          \  
  25.     __max1 > __max2 ? __max1: __max2; })  
  26.   
  27. /* 
  28.  * swap - swap value of @a and @b 
  29.  */  
  30. #define swap(a, b) \  
  31.     do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)  

swap是交换两个变量的值的宏,可以支持所有的基本类型。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值