zoukankan      html  css  js  c++  java
  • linux tricks 之 BUILD_BUG_ON_ZERO.

    -------------------------------------------
    本文系作者原创, 欢迎大家转载!
    转载请注明出处:netwalker.blog.chinaunix.net
    -------------------------------------------
     
    尽管在大多数时候只需关心代码运行的正确性,但是很多时候需要在编译期间就发现这些潜在的致命错误。内核提供了两个有力的宏定义:
    1 include/linux/kernel.h
    2 /* Force a compilation error if condition is true */
    3 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
    4 
    5 /* Force a compilation error if condition is true, but also produce a
    6    result (of value 0 and type size_t), so the expression can be used
    7    e.g. in a structure initializer (or where-ever else comma expressions
    8    aren't permitted). */
    9 #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]的错误定义相一致。如果不熟悉它,那么将很难根据警告找到出错的真正位置:

    1 xxx.c:42: 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。另外可能需要为了兼容性考虑,可能需要定义一些别名,比如:

    1 include/linux/net.h
    2 #define SOCK_CLOEXEC O_CLOEXEC

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

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

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

     
     1 struct map
     2 {
     3   int used[2];        /* 8 */
     4   int empty[5];        /* 20 */    
     5     
     6   char pad[32 - 28];
     7 } men = {{1, 2}, {0, 3, 4, 5, 6}};
     8 
     9 int main()
    10 {
    11   BUILD_BUG_ON(sizeof(men) != 32);
    12   printf("BUILD_BUG_ON_ZERO(0):%d, %d
    ", BUILD_BUG_ON_ZERO(0), sizeof(men));
    13     
    14   return 0;
    15 }
  • 相关阅读:
    LeetCode 79. 单词搜索
    LeetCode 1143. 最长公共子序列
    LeetCode 55. 跳跃游戏
    LeetCode 48. 旋转图像
    LeetCode 93. 复原 IP 地址
    LeetCode 456. 132模式
    LeetCode 341. 扁平化嵌套列表迭代器
    LeetCode 73. 矩阵置零
    LeetCode 47. 全排列 II
    LeetCode 46. 全排列
  • 原文地址:https://www.cnblogs.com/3me-linux/p/6210573.html
Copyright © 2011-2022 走看看