inline/ 宏展开 用代码区体积换取运行时速度适合小而频繁调用的函数。一、普通写法1,#defineSIZEOF(arr)(sizeof(arr)/sizeof((arr)[0]))(sizeof(arr)/sizeof((arr)[0]))2重要的警告非常容易出错的地方这个宏非常危险最常见的坑就是cvoid func(int a[]) // 注意这里 a 是指针{int n SIZEOF(a); // 错误结果通常是 1 或 2取决于平台// …}原因数组作为函数参数时会退化decay为指针sizeof(a) 变成 sizeof(int*)而不是整个数组的大小。正确做法在函数里必须额外传递长度参数void func(int a[], size_t len)或者使用 C99 的变长数组VLA或其他方式但宏本身无法自动处理。3,或者直接用现代 C 的方式推荐C99static inline 函数 _Generic 或其他技巧。C11可以用 _Static_assert 做编译期检查。二、c 17和之前版本cpp的写法1, C17和之后版本cpp直接用 std::size()std::size()2 模板函数C11类型安全templatetypenameT,std::size_t Nconstexprstd::size_tarray_size(T()[N]){returnN;}size_t lenarray_size(arr);这个方式最安全——如果传入指针而非数组编译直接报错而 sizeof 方法传指针会静默算出错误结果。一个常见陷阱voidfoo(intarr[]){// 错arr 已退化为指针sizeof(arr) 8指针大小size_t wrongsizeof(arr)/sizeof(arr[0]);}数组作为函数参数传递时会退化为指针sizeof 就失效了。这也是 C17std::size()/ C11 模板方法存在的意义之一。三、Linux内核写法Linux 内核经典写法的核心思想是正常计算数组长度如果传入的是指针在编译期报错Linux 风格ARRAY_SIZE#defineARRAY_SIZE(arr)(sizeof(arr)/sizeof((arr)[0])__must_be_array(arr))#define__must_be_array(a)BUILD_BUG_ON_ZERO(__same_type((a),(a)[0]))#define__same_type(a,b)__builtin_types_compatible_p(typeof(a),typeof(b))#defineBUILD_BUG_ON_ZERO(e)((int)(sizeof(struct{int:-!!(e);})))使用示例正确数组intnums[10];intnARRAY_SIZE(nums);// n 10错误指针编译时报错int*pnums;intnARRAY_SIZE(p);// 编译失败这正是它的价值把运行时 bug 提前到编译期。原理解释1. 正常长度计算sizeof(arr)/sizeof(arr[0])例如intarr[10];40/4102. 判断是不是数组__same_type((a),(a)[0])如果a是数组inta[10]typeof(a)int[10]typeof(a[0])int*类型不同 → false指针int*atypeof(a)int*typeof(a[0])int*类型相同 → true3. 指针时报错BUILD_BUG_ON_ZERO(true)制造非法位域宽度编译器直接报错。为什么这版强相比普通#defineARRAY_SIZE(a)(sizeof(a)/sizeof(a[0]))它多了✔ 防止传指针✔ 防止函数参数退化数组✔ 零运行时开销✔ 编译期发现问题实际建议现代 GCC/Clang你可以直接用这版#defineARRAY_SIZE(arr)\(sizeof(arr)/sizeof((arr)[0])\BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(__typeof__(arr),__typeof__((arr)[0]))))注意这依赖GCCClang不是标准 C89/C99 写法。如果做嵌入式 / MCU 开发很多编译器不支持typeof那要写兼容版。建议工业级如果你是Linux / Android / GCC 项目直接用上面内核版。STM32 / Keil / IAR用简化版#defineARRAY_SIZE(a)(sizeof(a)/sizeof((a)[0]))额外提醒即使 Linux 版也不能用于voidfoo(inta[]){ARRAY_SIZE(a);// 参数已退化为指针会报错这是好事}总结内核版本质是数组正常算长度指针直接不给过编译这就是高手写法。其他写法包括C11 标准版 ARRAY_SIZE不靠 GCC 扩展或者MSVC 可用版 ARRAY_SIZE或者2026 年最强泛型宏版。