(void) (_x == _y)
【整理】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,即:
- #define min(x, y) ({ \
- const typeof(x) _x = (x); \
- const typeof(y) _y = (y); \
- (void) (&_x == &_y); \
- _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)相关推荐
- (转载) min()的宏定义中的(void) (_x == _y)的含义
Original Address:http://www.crifan.com/2010/08/13/order_min__macro_definition_void_amp__x__amp__y_th ...
- pandas,pd.merge合并后出现2个后缀“_x“,“_y“
例子:df_fund = pd.merge( df_fund, df_perf , left_on="基金代码", right_on="基金代码" ) left ...
- C语言再学习 -- 关键字void
参看:C语言关键字 void 用途: 1.对函数返回的限定,用于强调函数没有返回值.如,void func(int x); 2.对函数参数的限定,用于强调函数没有任何参数.如,int func(voi ...
- linux标准c和c编译器6,linux内核中GNU C和标准C的区别
linux内核中GNU C和标准C的区别 今天看了一下午的linux内核编程方面的内容,发现linux 内核中GNU C与标准C有一些差别,特记录如下: linux 系统上可用的C编译器是GNU C编 ...
- linux内核能否扩展,Linux内核用到的GCC扩展
GNC CC是一个功能非常强大的跨平台C编译器,它对C 语言提供了很多扩展,这些扩展对优化.目标代码布局.更安全的检查等方面提供了很强的支持.本文把支持GNU 扩展的C 语言称为GNU C. Linu ...
- 详解 GNU C 标准中的 typeof 关键字
如果你是 C++ 程序员,应该接触过 C++11 里的 decltype 操作符,它的作用是自动推导表达式的数据类型,以解决泛型编程中有些类型由模板参数决定而难以(甚至不可能)表示的问题.其实这个特性 ...
- 【嵌入式】C语言高级编程-container_of宏(04)
00. 目录 文章目录 00. 目录 01. typeof 关键字 02. typeof与宏结合 03. typeof在内核源码中应用 04. container_of 宏分析 05. contain ...
- 【嵌入式】C语言高级编程-语句表达式(03)
00. 目录 文章目录 00. 目录 01. C语言的表达式 02. C语言的语句 03. C语言中的代码块 04. C语言中的语句表达式 05. 宏中使用语句表达式 06. Linux内核应用示例 ...
- 【C语言】Linux内核源码--min,swap宏定义
Linux3.5的部分宏定义在linux-3.5/include/linux/kernel.h的头文件中有定义 一: 最大值和最小值相关的宏 /** min()/max()/clamp() macro ...
- 《Linux4.0设备驱动开发详解》笔记--第三章:Linux下的C编程特点
3.1 Linux编码风格 参考文章:Documentation/CodingStyle 缩进用TAB {}使用: 对于结构体.if.for.while以及switch语句,"{" ...
最新文章
- OSChina 周六乱弹 —— 中国历史上路子最野的人
- 日期时间函数(1)-time()gmtime()strftime()localtime()
- Science nature合集 2021年度上半年
- lucene、solr、nutch三者的关系
- 震惊!上手就是快,GitHub18.5K标星,超实用的Python资源
- 团队任务2:冲刺前的准备
- nginx redis mysql_Nginx + Lua + Kafka + Redis + Mysql
- 小程序入门学习01--Hello World
- 在markdown (csdn)博客上输出 右下小标,右上小标。
- SharePoint 用户配置文件服务
- 前端----表格的具体使用(jquery)
- 22、redis中数据库默认是多少个db 及作用?
- “System.ComponentModel.Win32Exception配额不足,无法处理此命令。”问题
- 电脑linux 开启热点hostapt,在Ubuntu系统的电脑上开启无线热点全攻略
- 必须要知道的多媒体知识-音视频编解码-h265、h264-直播-点播
- 网页抓取软件Wget用法详解
- easy excel date 类型解析报错_两个日期相差多少天,你还在一天天的数吗?用Excel轻松完成计算...
- 一分钟快速了解边缘计算
- 支撑支付宝双11的核心架构
- 《土地公婆》钟久夫邓天晴演绎梁祝爱情
热门文章
- 尽量使用条件属性(Conditional Attribute)而不是#if/#endif预处理
- 42、最大子序和(python)
- sxssfworkbook 设置单元格大小_Offset属性和Resize属性相结合,完美实现选择区域大小的改变...
- python 小数乘法_《包装》——小数乘法
- 华为主题锁屏壁纸换不掉_华为手机中的这些默认设置一定要改,不然会导致手机卡顿加快耗电...
- linux6.5输错密码锁定,干货分享:解决redhat6.5登陆后跳回Login,循环登陆问题
- mapper的更多细节,日志配置、核心文件的配置等
- 如何将一个集合转换成json格式?
- ila数据导入matlab,MATLAB读取Xilinx ILA核保存的.ila文件中的两列数据,并输出到文件保存...
- 美国慈善机构Kars4Kids意外泄露了上万名捐赠者的个人信息