from net/mac80211/sta_info.c, define at include/linux/kernel.h
1 2 3 4 5 |
/** * ARRAY_SIZE – get the number of elements in array @arr * @arr: array to be sized */ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) |
__must_be_array: 檢查 a 是否為 array,當 a 為 array 時,會因為 &(a)[0] 變成 pointer,而讓 __same_type 產生 0 的結果,反之如果 a 為 pointer,因為 &(a)[0] 仍然是 pointer, __same_type 回傳 1 而導致 BUILD_BUG_ON_ZERO 產生編譯 error,從而檢查傳入的 object 是否為 array:
1 2 |
/* &a[0] degrades to a pointer: a different type from an array */ #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) |
BUILD_BUG_ON_ZERO: 當 BUILD_BUG_ON_ZERO 的值為 true 的時候,編譯時會發出 error (error: negative width in bit-field ‘’)。但值為 false 時會產生 value 0:
1 2 3 4 5 6 7 |
/* * 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(struct { int:(-!!(e)); })) |
__same_type: 根據不同的編譯器有不同的版本,這邊以 gcc 為例,使用的 gcc 的 builtin-function __builtin_types_compatible_p
, 當兩者 type 相同時回傳 1,否則回傳 0:
1 |
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) |
範例程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <stdio.h> #include <stdlib.h> int main() { int *a = malloc(sizeof(int) * 10); int b[10]; printf(“%d\n”, __builtin_types_compatible_p(typeof((a)), typeof((&(a)[0])))); printf(“%d\n”, __builtin_types_compatible_p(typeof(b), typeof(&(b)[0]))); printf(“%d\n”, –!!(0)); printf(“%d\n”, –!!(1)); sizeof(struct { int: (–!!(0)); }); sizeof(struct { int: (–!!(1)); }); } |
編譯結果:
1 2 3 4 |
$ gcc –O0 –g3 c.c c.c: In function ‘main’: c.c:14:16: error: negative width in bit–field ‘<anonymous>’ sizeof(struct { int: (–!!(1)); }); |
Leave a Reply