typeof是gcc的扩展功能,比较简单,是用来取得参数类型,具体可参考gcc官网的解释.

https://gcc.gnu.org/onlinedocs/gcc/Typeof.html

-------------------------------------------
本文系作者原创, 欢迎大家转载!
转载请注明出处:netwalker.blog.chinaunix.net
-------------------------------------------

由于Linux代码采用Gcc编译器编译,所以它可以采用Gcc对C语言的扩展特性,以实现高效的代码。其中运用非常广泛的扩展就是复合语句。Gcc把包含在圆括号和大括号双层括号内的复合语句看作是一个表达式,它可以出现在任何允许表达式的地方,而复合语句中可以声明局部变量,以及循环条件判断等复杂处理。而表达式的最后一条语句必须是一个表达式,它的计算结果作为返回值。

 int a = ({typeof(a) _a = ; ++_a;});

上例中符合表达式中声明了局部变量_a,而返回值为++_a的结果,所以a的值为1。基于这种扩展,内核可以通过在复合语句中定义局部变量而表面自加自减运算符的副作用问题。内核中的min_t和max_t宏就是这样实现的。

 include/linux/kernel.h
#define min_t(type, x, y) ({ \
type __min1 = (x); \
type __min2 = (y); \
__min1 < __min2 ? __min1: __min2; }) #define max_t(type, x, y) ({ \
type __max1 = (x); \
type __max2 = (y); \
__max1 > __max2 ? __max1: __max2; })

尽管多数时候通过使用这类宏,可以避免参数的副作用,但是这会增加内存的开销和执行效率,所以如果能够保证参数不存在副作用,那么使用通常的如下定义即可:

 #define min(a, b) ((a) > (b)? (b) : (a))
#define max(a, b) ((a) > (b)? (a) : (b))

以上的min_t和max_t宏适需要提供数据类型,typeof的出现使这一步也可被省略。

 include/linux/kernel.h
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; }) #define max(x, y) ({ \
typeof(x) _max1 = (x); \
typeof(y) _max2 = (y); \
(void) (&_max1 == &_max2); \
_max1 > _max2 ? _max1 : _max2; })

观察min和max的实现,它们通过typeof获取x和y的类型,然后定义局部变量以消除参数副作用。

思考问题:注意到中间的比较运算,

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

这两行代码是用来做类型检查的,如果x和y的类型不同,那么编译器将提示如下警告信息,这对检查代码很有帮助。

 xxx.c:: warning: comparison of distinct pointer types lacks a cast

那么,类型检查是如何生效的呢?在stackoverflow上找到解释如下:

This provides for type checking, equality between pointers shall be between compatible types and gcc will provide a warning for cases where this is not so.

We can see that equality between pointers requires that the pointers be of compatible types from the draft C99 standard section 6.5.9 Equality operators which says:

One of the following shall hold:

and includes:

both operands are pointers to qualified or unqualified versions of compatible types;

and we can find what a compatible type is from section 6.2.7 Compatible type and composite type which says:

Two types have compatible type if their types are the same

This discussion on osnews also covers this and it was inspired by the the GCC hacks in the Linux kernel article which has the same code sample. The answer says:

has to do with typechecking.

Making a simple program:

int x = 10;
long y = 20;
long r = min(x, y);

Gives the following warning: warning: comparison of distinct pointer types lacks a cast

stackoverflow对此问题的讨论已经很清楚,简单的来说,c99标准约定,对于比较运算符  == 和 != 来说,如果比较的对象是指针,那么指针所指的对象类型必须一致,否则抛出上面的warning信息.

参考资料:http://stackoverflow.com/questions/5595593/min-macro-in-kernel-h

linux tricks 之 typeof用法.的更多相关文章

  1. Linux中find常见用法

    Linux中find常见用法示例 ·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \; find命令的参数 ...

  2. Linux关于watch的用法

    Linux关于watch的用法 2011-07-20      0个评论       收藏    我要投稿 watch 是一个非常实用的命令,基本所有的 Linux 发行版都带有这个小工具,如同名字一 ...

  3. [转]Linux中find常见用法示例

    Linux中find常见用法示例[转]·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \;find命令的参 ...

  4. Linux下find命令用法详解

    Linux下find命令用法详解   学神VIP烟火 学神IT教育:XueGod-IT   最负责任的线上直播教育平台   本文作者为VIP学员 烟火   第一部分:根据文件名查找   1.在当前目录 ...

  5. linux中make的用法

    一.linux中make的用法 目的:       基本掌握了make 的用法,能在Linux系统上编程.环境:       Linux系统准备:       准备三个文件:file1.c, file ...

  6. Linux中“!"的神奇用法

    前言 实际上,不起眼的“!”在linux中有着很多让你惊叹的妙用.本文就来细数那些“!”的神奇用法. 执行上一条命令 例如,在执行完上面一条命令后,可以使用下面的方式再次执行上一条命令: $ wher ...

  7. Linux中sed的用法实践

    Linux中sed的用法实践 参考资料:https://www.cnblogs.com/emanlee/archive/2013/09/07/3307642.html http://www.fn139 ...

  8. Linux中Sed的用法

    Linux中Sed的用法 sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法sed命令行格式为: ...

  9. Linux tar命令高级用法——备份数据

    Linux tar命令高级用法——备份数据 2015-12-31 Linux学习 Linux上有功能强大的tar命令,tar最初是为了制作磁带备份(tape archive)而设计的,它的作用是把文件 ...

随机推荐

  1. python 入门

    bool t, f = True, False print type(t) # Prints "<type 'bool'>"   字符串 hello = 'hello' ...

  2. win7打开网页老是提示下载网页解决办法

    方法:我的系统是windows 7 旗舰版, 解决方法可以自己手动去修复,方法是进入命令窗口. 开始--运行--cmd--sfc.exe--sfc/scannow   修复一下!

  3. delphi基本语法

    本文参考自<delphi2010语法手册> 1. 工程文件结构 源文件联系着unit单元,delphi主模块源文件格式为.dpr,其他模块为.pas,一个完整程序由一个.dpr和若干.pa ...

  4. POP3,全名为“Post Office Protocol - Version 3”,即“邮局协议版本3”

    POP3 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . POP3,全名为“Post Office Protocol - Version 3”,即“邮局协议版本3”.是TCP/IP ...

  5. 如何卸载lnmp

    转自:https://www.centos.bz/2011/07/howto-remove-lnmp/ killall nginx /etc/init.d/mysql stop killall mys ...

  6. QEMU-KVM中的多线程压缩迁移技术

    导读 目前的迁移技术,都是通过向QEMUFILE中直接写入裸内存数据来达到传送虚拟机的目的端,这种情况下,发送的数据量大,从而会导致更高的迁移时间(total time)和黑宕时间(downtime) ...

  7. sql注入攻击的预防函数

    /* 待更新 */ addslashes  htmlspecialchars  mysql_escape_string($string) mysql_real_escape_string($strin ...

  8. 调用python 报R6034 错误

    R6034 指的是:"An application has made an attempt to load the C runtime library incorrectly. Please ...

  9. Firemonkey的旁门左道[六]

    转载:http://blog.csdn.net/qustdong/article/details/9992033 今天还是讲讲和图形有关的事情,这次的难度再增加些,不是直接改源代码了, 而是通过RTT ...

  10. 解决Centos关闭You have new mail in /var/spool/mail/root提示

    昨天搬到阿里云了. 装的系统是Centos 6.3的加固版 今天查看内存的时候 出现一天奇怪的提示 You have new mail in /var/spool/mail/root 有的时候每敲一下 ...