Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

内核ARRAY_SIZE实现 #7

Open
leon0625 opened this issue Jan 16, 2018 · 0 comments
Open

内核ARRAY_SIZE实现 #7

leon0625 opened this issue Jan 16, 2018 · 0 comments
Labels

Comments

@leon0625
Copy link
Owner

内核ARRAY_SIZE实现

这个宏非常常用,实现大多都是#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])),今天要用这个宏,怕写错了,看了下内核怎么写的,一下就看懵逼了。

内核的实现如下:

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))

__must_be_array什么鬼

#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))

BUILD_BUG_ON_ZERO__same_type又是什么鬼

#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))

解析:

  1. __same_type
    __builtin_types_compatible_p是gcc内置的函数,从名字看应该是判断两个变量的类型是否一样
  2. BUILD_BUG_ON_ZERO
    这个就宏就值得一说了
    1. !!(e)表示e的布尔值。e为真,那么这个运算为1;e为假,这个运算为0
    2. -!!(e)就是乘个-1的意思,那么这个表达式为-1或0
    3. struct { int:-!!(e); } 表示定义了一个位域,因为上一步的计算为-1或0,那么这个位域展开为int:-1(这不合语法,编译会报错)或者int:0(合法)
    4. sizeof(struct { int:-!!(e); }),当上一步不合法时,会报错,否则sizeof计算出为0。
      总体而言,BUILD_BUG_ON_ZERO(e)这个宏的意思就是说,如果e不为0那么编译报错,如果e为0那么返回0。

总结:内核ARRAY_SIZE宏除了计算出数组大小外,还检查了参数是否是数组,如果不是数组编译直接报错。好强大,代码写错了,直接在编译的时候就检查出来了,而不是在运行时!!

参考:Linux Kernel 代码艺术——编译时断言

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant