文章总结: 本文介绍了Linux内核中BUILD_BUG_ON宏的实现原理。利用C语言无法创建负长度数组且数组长度编译期求值的特性,通过sizeof(char[1-2*!!(condition)])实现编译期断言。!!(condition)将条件布尔化为0或1,条件为真时产生负长度数组触发编译错误。相比早期使用命名数组的实现,sizeof方案避免了命名空间污染和运行时开销,是static_assert出现前的经典编译期检查技术。 综合评分: 78 文章分类: 安全开发,代码审计,二进制安全
【赤石C++】BUILD_BUG_ON 宏
原创
crackme.net crackme.net
crackme安全实验室
2026年2月8日 18:36 河南
BUILD_BUG_ON
考虑一个问题:在没有 static_assert 的年代,如何确保在编译期抛出错误?
我们知道,在 C 语言中,无法创建负长度数组且数组长度会在编译期求值
// 无法创建负长度数组
char a[-1];
// 数组长度编译期求值
char a[2 * 3]; // sizeof(a) == 6
所以,利用这个特性就可以实现一个简易的 static_assert,当条件不满足时创建一个负数长度数组保证在编译期抛出错误
#define my_static_assert(condition) char a[condition ? 1 : -1]
但引入了几个新的问题:命名空间污染和运行时开销
C 语言不支持匿名数组,声明数组时必须指定变量名(声明必须绑定到标识符),会造成命名空间污染
// 不支持匿名数组,这是非法语句
char[1];
此外,在编译器优化能力不足时,多余的数组还可能导致多占用栈空间造成额外的运行时开销
解决方法是使用 sizeof 包裹,我们知道,sizeof 后面可以跟一个类型名(更准确的说法是“类型抽象声明符”),所以 sizeof(char[1]) 是合法语句,因为这里的 char[1] 并不是在创建数组,而是在描述一个类型,sizeof 只关心这个类型的大小,不需要创建实际对象
// 合法语句
sizeof(char[1]);
不会造成命名空间污染,不会造成运行时开销(sizeof 也是编译期求值),Linux 内核的 BUILD_BUG_ON 就是这样实现的
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
首先,!!(condition) 把任意表达式强制转为 0 或 1(布尔化)
当表达式为 1 时,宏被展开为 sizeof(char[-1]),否则被展开为 sizeof(char[1])
// 正常编译
sizeof(char[1]);
// 抛出错误
sizeof(char[-1]);
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:crackme安全实验室 crackme.net crackme.net《【赤石C++】BUILDBUGON 宏》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论