【整理】min()的宏定义中的(void) (&_x == &_y)的含义

转自:

http://hi.baidu.com/serial_story/blog/item/b6fd81098b5b1b296a60fb4d.html

近日无意间发现,关于常见的min的宏定义,在Linux中是这样的:

/*
* min()/max()/clamp() macros that also do
* strict type-checking.. See the
* "unnecessary" pointer comparison.
*/
#define min(x, y) ({     \
typeof(x) _x = (x);    \
typeof(y) _y = (y);    \
(void) (&_x == &_y);   \
_x < _y ? _x : _y; })

关于其中的:

(void) (&_x == &_y);

很是疑惑,表面看起来,这句话,好像不起作用,算是一句废话,所以去找了一下别人的解释,才大概搞懂是啥意思。

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

gcc 编辑器有个这个选项     某个未使用的值会发出警告

比如,如果你编译下面这段代码:

int x = 2;
char y = 3;
int m;
m = min(x,y);

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

int * == char *;

因此编译器就会提示你:

warning: comparison of distinct pointer types lacks a cast

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

所以,总结起来就是:

(void) (&_x == &_y); 用于判断输入的两个值的类型是否是一致的。如果不一致,那么编译器就会做出如下警告:warning: comparison of distinct pointer types lacks a cast

【提示】

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

  1. #define min(x, y) ({ \
  2. const typeof(x) _x = (x); \
  3. const typeof(y) _y = (y); \
  4. (void) (&_x == &_y); \
  5. _x < _y ? _x : _y; })

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,就可以避免此类问题了。

(void) (_x == _y)相关推荐

  1. (转载) min()的宏定义中的(void) (_x == _y)的含义

    Original Address:http://www.crifan.com/2010/08/13/order_min__macro_definition_void_amp__x__amp__y_th ...

  2. pandas,pd.merge合并后出现2个后缀“_x“,“_y“

    例子:df_fund = pd.merge( df_fund, df_perf , left_on="基金代码", right_on="基金代码" ) left ...

  3. C语言再学习 -- 关键字void

    参看:C语言关键字 void 用途: 1.对函数返回的限定,用于强调函数没有返回值.如,void func(int x); 2.对函数参数的限定,用于强调函数没有任何参数.如,int func(voi ...

  4. linux标准c和c编译器6,linux内核中GNU C和标准C的区别

    linux内核中GNU C和标准C的区别 今天看了一下午的linux内核编程方面的内容,发现linux 内核中GNU C与标准C有一些差别,特记录如下: linux 系统上可用的C编译器是GNU C编 ...

  5. linux内核能否扩展,Linux内核用到的GCC扩展

    GNC CC是一个功能非常强大的跨平台C编译器,它对C 语言提供了很多扩展,这些扩展对优化.目标代码布局.更安全的检查等方面提供了很强的支持.本文把支持GNU 扩展的C 语言称为GNU C. Linu ...

  6. 详解 GNU C 标准中的 typeof 关键字

    如果你是 C++ 程序员,应该接触过 C++11 里的 decltype 操作符,它的作用是自动推导表达式的数据类型,以解决泛型编程中有些类型由模板参数决定而难以(甚至不可能)表示的问题.其实这个特性 ...

  7. 【嵌入式】C语言高级编程-container_of宏(04)

    00. 目录 文章目录 00. 目录 01. typeof 关键字 02. typeof与宏结合 03. typeof在内核源码中应用 04. container_of 宏分析 05. contain ...

  8. 【嵌入式】C语言高级编程-语句表达式(03)

    00. 目录 文章目录 00. 目录 01. C语言的表达式 02. C语言的语句 03. C语言中的代码块 04. C语言中的语句表达式 05. 宏中使用语句表达式 06. Linux内核应用示例 ...

  9. 【C语言】Linux内核源码--min,swap宏定义

    Linux3.5的部分宏定义在linux-3.5/include/linux/kernel.h的头文件中有定义 一: 最大值和最小值相关的宏 /** min()/max()/clamp() macro ...

  10. 《Linux4.0设备驱动开发详解》笔记--第三章:Linux下的C编程特点

    3.1 Linux编码风格 参考文章:Documentation/CodingStyle 缩进用TAB {}使用: 对于结构体.if.for.while以及switch语句,"{" ...

最新文章

  1. OSChina 周六乱弹 —— 中国历史上路子最野的人
  2. 日期时间函数(1)-time()gmtime()strftime()localtime()
  3. Science nature合集 2021年度上半年
  4. lucene、solr、nutch三者的关系
  5. 震惊!上手就是快,GitHub18.5K标星,超实用的Python资源
  6. 团队任务2:冲刺前的准备
  7. nginx redis mysql_Nginx + Lua + Kafka + Redis + Mysql
  8. 小程序入门学习01--Hello World
  9. 在markdown (csdn)博客上输出 右下小标,右上小标。
  10. SharePoint 用户配置文件服务
  11. 前端----表格的具体使用(jquery)
  12. 22、redis中数据库默认是多少个db 及作用?
  13. “System.ComponentModel.Win32Exception配额不足,无法处理此命令。”问题
  14. 电脑linux 开启热点hostapt,在Ubuntu系统的电脑上开启无线热点全攻略
  15. 必须要知道的多媒体知识-音视频编解码-h265、h264-直播-点播
  16. 网页抓取软件Wget用法详解
  17. easy excel date 类型解析报错_两个日期相差多少天,你还在一天天的数吗?用Excel轻松完成计算...
  18. 一分钟快速了解边缘计算
  19. 支撑支付宝双11的核心架构
  20. 《土地公婆》钟久夫邓天晴演绎梁祝爱情

热门文章

  1. 尽量使用条件属性(Conditional Attribute)而不是#if/#endif预处理
  2. 42、最大子序和(python)
  3. sxssfworkbook 设置单元格大小_Offset属性和Resize属性相结合,完美实现选择区域大小的改变...
  4. python 小数乘法_《包装》——小数乘法
  5. 华为主题锁屏壁纸换不掉_华为手机中的这些默认设置一定要改,不然会导致手机卡顿加快耗电...
  6. linux6.5输错密码锁定,干货分享:解决redhat6.5登陆后跳回Login,循环登陆问题
  7. mapper的更多细节,日志配置、核心文件的配置等
  8. 如何将一个集合转换成json格式?
  9. ila数据导入matlab,MATLAB读取Xilinx ILA核保存的.ila文件中的两列数据,并输出到文件保存...
  10. 美国慈善机构Kars4Kids意外泄露了上万名捐赠者的个人信息