-------------------------------------------
本文系作者原创, 欢迎大家转载!
转载请注明出处:netwalker.blog.chinaunix.net
-------------------------------------------
 
尽管在大多数时候只需关心代码运行的正确性,但是很多时候需要在编译期间就发现这些潜在的致命错误。内核提供了两个有力的宏定义:
 include/linux/kernel.h
/* Force a compilation error if condition is true */
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) /* Force a compilation error if condition is true, but also produce a
result (of value 0 and type size_t), so the expression can be used
e.g. in a structure initializer (or where-ever else comma expressions
aren't permitted). */
#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)

注意核心表达式sizeof(char[1 - 2*!!(condition)])的作用,首先对条件表达式进行两次取反,这可以保证进行1 - 2*!!(condition)的结果只有两种值:条件为0时结果为1或者不为0则结果为-1,显然char[-1]将会导致编译器报错。注意:两次取反的目的是为了将表达式的值转换为逻辑值。

  • BUILD_BUG_ON:只有条件condition为0时可编译,但不返回值,否则编译器报错。
  • BUILD_BUG_ON_ZERO:只有条件e为0时返回0,否则编译器报错。

总结:BUILD_BUG_ON和BUILD_BUG_ON_ZERO作用类似,都是在参数为非0时编译报错,但是BUILD_BUG_ON_ZERO可以返回0值,BUILD_BUG_ON不可。编译器警告的格式如下,这与char[-1]的错误定义相一致。如果不熟悉它,那么将很难根据警告找到出错的真正位置:

 xxx.c:: error: size of array ‘type name’ is negative

目前内核对BUILD_BUG_ON_ZERO的使用有两处:一个是在数组大小计算中用来判定指针合法行的__must_be_array宏。另一个是对模块参数进行权限检查时的__module_param_call宏。
内核对BUILD_BUG_ON的使用则要普遍的多,它被用来做编译期间的参数检查,广泛存在于内核的源码文件中。某些情况下需要一个数据结构满足特定的大小,比如jffs2文件系统中的jffs2_raw_inode结构的大小必须为68。另外可能需要为了兼容性考虑,可能需要定义一些别名,比如:

 include/linux/net.h
#define SOCK_CLOEXEC O_CLOEXEC

则可以在编码时检测是否定义正确:

 net/socket.c
BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);

大多数情况下,它们属于调试信息,在调试完毕后需要移除,除非它们可以指示一些特定的信息,比如第一种情况用来强调数据结构的大小为固定值。一个详细的示例如下,如果struct map结构体的大小不为32,则编译时报错。

 struct map
{
int used[]; /* 8 */
int empty[]; /* 20 */ char pad[ - ];
} men = {{, }, {, , , , }}; int main()
{
BUILD_BUG_ON(sizeof(men) != );
printf("BUILD_BUG_ON_ZERO(0):%d, %d\n", BUILD_BUG_ON_ZERO(), sizeof(men)); return ;
}

linux tricks 之 BUILD_BUG_ON_ZERO.的更多相关文章

  1. linux tricks 之 FIELD_SIZEOF.

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

  2. linux tricks 之 container_of.

    转载:http://blog.chinaunix.net/uid-20608849-id-3027972.html 由于内核中定义了很多复杂的数据结构,而它们的实例中的成员在作为函数参数传递的时,函数 ...

  3. linux tricks 之 bitmap分析.

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

  4. linux tricks 之数据对齐。

    转载:http://blog.chinaunix.net/uid-20608849-id-3027953.html   内核为了保持最大的兼容性和代码灵活性,不可能直接对某个数据类型定义它的大小范围. ...

  5. linux tricks 之VA系列函数.

    VA函数(variable argument function),参数个数可变函数,又称可变参数函数.C/C++编程中,系统提供给编程人员的va函数很少.*printf()/*scanf()系列函数, ...

  6. linux tricks 之 typeof用法.

    typeof是gcc的扩展功能,比较简单,是用来取得参数类型,具体可参考gcc官网的解释. https://gcc.gnu.org/onlinedocs/gcc/Typeof.html ------- ...

  7. linux tricks 之 ALIGN解析.

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

  8. Linux tricks

    Environment Settings Path Globally set path is in /etc/profile; or the user's .bash_profile for part ...

  9. linux tricks 之 roundup.

    转载:http://stackoverflow.com/questions/1010922/question-about-round-up-macro 以下内容转载自stackoverflow关于 r ...

随机推荐

  1. Java多线程基础(一)

    一.基本概念 线程状态图包括五种状态 1.新建状态(New):线程对象被创建后,就进入新建状态.例如,Thread thread=new Thread(); 2.就绪状态(Runnable):也被称为 ...

  2. Nginx变量的实现机制

    Nginx有两种定义变量的方式,一种是在配置文件中使用set指令(由rewrite模块提供支持),另一种是在模块内定义变量. 变量相关结构体: struct ngx_http_variable_s { ...

  3. BurpSuite实例教程

    很久以前就看到了Burp suite这个工具了,当时感觉好NB,但全英文的用起来很是蛋疼,网上也没找到什么教程,就把这事给忘了.今天准备开始好好学习这个渗透神器,也正好给大家分享下.(注:内容大部分是 ...

  4. nginx负载均衡的配置方法

    upstream www.***.com { server ; server ; server ; } server { listen ; server_name www.***.com; #char ...

  5. CentOS 7 使用经验(更新中)

    首先说一下写这篇博客的初衷. 由于公司这一期的产品准备支持的环境有CentOS 7.MySql 5.6.Java 8.Tomcat 8等等,并且因为人员严重不足,我本月的开发任务在原有的基础上又加上了 ...

  6. MVC利用Routing实现多域名绑定一个站点、二级域名以及二级域名注册Area

    最近有这么个需求:在一个站点上绑定多个域名,每个域名进去后都要进入不同的页面.实现了这个功能以后,对于有多个域名,且有虚拟空间,但是虚拟空间却只匹配有一个站点的用户来说,可以节省很多小钱钱. 很久以前 ...

  7. 《C++代码设计与重用》 书评

    作者:唐风 主页:www.cnblogs.com/liyiwen   前几个星期买了,一直没有直接细翻,买的时候看了背面的两个推荐,一个是孟岩,一个是Scott Meyers(Effective C+ ...

  8. 没玩过这些微信小游戏你就out了

    你确定没玩过下面这些微信小游戏?是不是有点out了?赶紧添加微信号kangfuyk,回复H5马上畅玩! 当然了,扫一下二维码关注后回复H5更快捷噢! 微信小游戏列表,持续更新中 辨色大比拼!心理游戏 ...

  9. 添加删除虚拟ip

    添加  ip -f inet addr add 192.168.1.245/32 brd 192.168.1.245 dev ens32 删除  ip -f inet addr del 192.168 ...

  10. springmvc 定时器

    CronTrigger配置格式: 格式: [秒] [分] [小时] [日] [月] [周] [年] 序号 说明  是否必填  允许填写的值 允许的通配符 1  秒  是  0-59    , - *  ...