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

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

近日无意间发现,关于常见的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个不一样的指针类型进行比较操作,则会引起编译器产生一个编译警告,提示你这两个值的类型不同。

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

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

【引用】

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

http://hi.baidu.com/huahua9901/blog/item/9640223f2a37773470cf6cc4.html

2。如下的宏定义中(void) (&_x == &_y);是怎么做到判断类型的?

http://linux.chinaunix.net/bbs/viewthread.php?tid=1161263

3。Linux内核中的Min和Max函数

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

防君子不防也无法防小人的声明: 
如未注明转载则均为crifan原创,对于原创文章,转载请注明出处:在路上 - on the way 
本文链接:【整理】min()的宏定义中的(void) (&_x == &_y)的含义

(转载) min()的宏定义中的(void) (_x == _y)的含义相关推荐

  1. define宏定义中的#,##,@#及\符号

    define宏定义中的#,##,@#及\符号 在#define中,标准只定义了#和##两种操作.#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串. 1.# (string ...

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

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

  3. c语言长度宏定义运算符,C语言在宏定义中使用语句表达式和预处理器运算符

    语句表达式的亮点在于定义复杂功能的宏.使用语句表达式来定义宏,不仅可以实现复杂的功能,而且还能避免宏定义带来的歧义和漏洞.下面以一个简单的最小值的宏为例子一步步说明. 1.灰常简单的么,使用条件运算符 ...

  4. 宏定义中的 ## ... __VA_ARGS__

    宏定义中的##操作符和... and _ _VA_ARGS_ _ 1.Preprocessor Glue: The ## Operator 预处理连接符:##操作符 Like the # operat ...

  5. #与##在宏定义中的--宏展开

    #与##在宏定义中的--宏展开 #include <stdio.h> #define f(a,b) a##b #define g(a) #a #define h(a) g(a) int m ...

  6. ANSI C and Microsoft C++中常用的预定义宏以及 宏定义中 # 和 ## 的区别

    ANSI C and Microsoft C++中常用的预定义宏以及 宏定义中 # 和 ## 的区别 第一部分,常见的预定义宏 第二部分,# 和 ## 再宏定义中的使用说明 第三部分,类似 #prag ...

  7. C语言 带参数宏定义中 # 和 ## 知识点总结、代码分析

    目录 一.宏定义中 "#"知识点 1.直接转换字符串,不展开. 2.转换出的结果一定是"字符串". 二.宏定义中 ## 知识点 1.应用场景 2."# ...

  8. 巧用c语言宏定义实现自动注释调试代码,C语言宏定义中的特殊用法

    C宏定义中的特殊用法 在分析一些C源码时,经常会遇到各种宏定义操作,本文即总结一下C语言宏定义中常见的预定义宏.调试宏:宏的条件编译用法及特殊的宏关键字用法. #undef 限定宏的作用域 一般来讲宏 ...

  9. C语言宏定义中#号的作用

    C语言宏定义中#号的作用 前言 #号的作用 前言 最近,在阅读uboot的源码过程中,发现了一段宏定义代码: #define U_BOOT_CMD_MKENT_COMPLETE(_name, _max ...

最新文章

  1. 【建站系列教程】1、前言
  2. areas where akka is being deployed into production
  3. 在Forge Viewer上显示自订义属性
  4. 为何断点不停 Application_Start()方法
  5. java xslt 数据转换_如何将xslt结果转换为Java对象?
  6. Exynos4412裸机开发——中断处理
  7. kafka Failed to send messages after 3 tries 问题解决
  8. JAVA minaio模型_分布式系统之Java IO模型
  9. Maven学习总结(12)——eclipse中构建多模块maven项目
  10. delete kubectl pod_kubectl delete
  11. 万年历c语言代码3000年,求万年历代码!
  12. word没有显示endnote_word 未显示EndNote工具条的解决方法
  13. 登录服务器的详细步骤
  14. 非容器化jenkins 连接k8s 集群
  15. Debian 执行apt-get update失败提示:请使用 apt-cdrom,通过它可以让 APT 识别该盘片。apt-get upgdate 不能被用来加入新的盘片
  16. 神起网络游戏如何推广代理?
  17. Android开源项目分类汇总【畜生级别】[转]
  18. 2021-IP地址详解02
  19. 前端ES5/JavaScript高频面试题 及答案
  20. Office共享(word,excel等)2021-09-21

热门文章

  1. 网易笔试编程题java_2017年网易校招笔试JAVA研发编程题
  2. vue e-charts按需引入
  3. poj1942(求组合数)
  4. Docker——Docker Compose
  5. 【PHP高级特性】之反射
  6. idea下一次Jar包依赖问题的解决过程
  7. python数据结构之树
  8. 直播平台虚拟币与人民币的关系
  9. 一个C#读写Dxf的类库DXFLibrary
  10. 关于js获取radio和select的属性并控制