Linux内核代码中max和min宏的实现以及语句表达是({})的应用

Linux内核代码中有很多比较精巧的程序设计技巧,include/linux/kernel.h中实现max和min宏就是其中的一部分。

我们先来看一下普通的max和min一般怎么写:

#define min(x,y) ((x)>(y)?(y):(x))

#define max(x,y) ((x)>(y)?(x):(y))

但这么写有一个小风险,请看以下调用:

int x = 2;y = 1

printf("%d/n", max(x++, y++)); 

调用结束后会发现,x被加了2,主要是因为max被展开后如下:

((x++) > (y++) ? (x++) : (y++))

很明显,这么做是不安全的,那我们来看Linux Kernel是如何做的:

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

这么做主要涉及以下几个知识点:

1、typeof(x)

找出x的数据类型

2、语句表达是({S1;S2;...;Sn;})

总的语句表达是的值是Sn,这个技巧我之前写代码是也用到过,呵呵

3、(void) (&_x == &_y);的巧妙

这个主要是用来判断x,y数据类型是否一样,利用了编译器的一个小特性:不同数据类型的变量进行比较时会产生Warning,如果Makefile比较严格的话,会产生Error

关于这一点,很多人写,但都没写到点子上,以下几篇都很好:

http://www.armfans.net/thread-1527-1-1.html

http://my.oschina.net/pathenon/blog/63492

http://www.wypblog.com/archives/237

收藏于 2013-09-07

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端小叙

vue路由跳转报错解决

1084
来自专栏Python研发

分分钟带你理解单例

答:单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实列存在,当你希望整个系统中只能出现一个实列时...

942
来自专栏菩提树下的杨过

javascript:FF/Chrome 与 IE 动态加载元素的区别

今天在写一段js时,发现IE与FF在动态加载Html元素时,有一些差别,看下面的代码: <!doctype html> <html> <head> <titl...

20810
来自专栏web前端

select 遇到的坑

一、select遇到的坑      1、select赋默认值--多选和单选           1.1     单选:$('#id').val( value )...

22110
来自专栏猿人谷

getch和getchar的区别

函数名: getch(); 功 能: 从控制台无回显地取一个字符 函数名: getchar(); 功 能: 从stdin流中读字符 函数名: scanf...

1779
来自专栏Coding01

链式编程

链式编程或者链式写法,是将多个方法 (函数) 通过点号 (.) 或者 (->)等符号链接在一起成为一句代码,这样不仅可以增强代码的可读性,而且每次链接,都是对对...

713
来自专栏Golang语言社区

Golang语言 与 C 语言 的比较学习

对于MarkDown 编译器没有自动保存功能这件事情, 我表示严重的厌恶。 一个来小时的整理化为乌有,而且居然还不能导入到HTML编辑器, 真是无法忍受! 关键...

3187
来自专栏安恒网络空间安全讲武堂

[Web安全]PHP伪协议

[Web安全]PHP伪协议 最近php伪协议的各种神奇妙用好像突然又常常提到了,php中支持的伪协议有下面这么多 复制代码 file:// — 访问本地文件...

2378
来自专栏java技术学习之道

一张图搞定Java原型模式

1185
来自专栏我是攻城师

Nodejs笔记(三)

3329

扫码关注云+社区