在编译时检查sizeof

本文介绍了如何在编译时通过BUILD_BUG_ON宏来检查struct的大小,确保它们满足特定的对齐要求。这种方法在Linux内核中被用于保证硬件兼容性和数组元素的正确对齐。
摘要由CSDN通过智能技术生成

今天在写文件系统时,想在编译时检查一些struct的大小,就发现了这篇blog,讲得是内核里面的BUILD_BUG_ON的实现,这个优雅精妙的实现让我对内核开发者的敬佩之情真是油然而生啊!!

有时候,我们在写C程序的时候需要对struct的大小做一些限制。比如说,struct需要以某些字节大小进行对齐,以符合硬件的支持(也许是某个设备的DMA缓冲区,要使用地址的低位做一些其他的计算),并且这些struct组成了一个数组,每个数组里面的struct都需要以字节8对齐。

有时候我们可以这样写

#if ((sizeof(struct mystruct) % 8 ) != 0)
#error "you screwed up struct mystruct again!"
#endif
但是这样不一定会成功,预处理器不一定会支持sizeof操作符,也不知道C的具体类型。或者,可以把它写到运行时代码里面:

if ((sizeof(struct mystruct) % 8 ) != 0) {
    printf("You screwed up mystruct again!\n");
    exit(1);
}
但是这样会产生额外的代码,消耗不必要的CPU时间,并且这个问题直到运行时才会发现这个BUG。

其实Linux内核里面已经有相关的macro解决这个问题,在include/linux/kernel.h:

#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
使用这个黑科技,我们可以在编译时就对struct大小进行检查

int main()
{
    /* check that you didn't screw up mystruct */
    BUILD_BUG_ON(sizeof(struct mystruct) % 8));
    return 0;
}
如果struct不是8的倍数,这个在编译时会报错;如果它是struct的倍数,这个语句不会产生任何运行时代码。完美符合我们的要求。

但是它是怎么运行的呢?

比如说,

 sizeof(char[1]); /* this gives you the size of a */
                  /* character array of 1. */
 sizeof(char[-11]); /* this doesn't compile */
这两条语句,第一条不会报错,第二条会报错。基于这个原理,我们就可以设计这个struct的sizeof检查了。

PS:下面这些我参考原blog简要解释以下BUILD_BUG_ON的实现,就不一一翻译了

!!(condition)
这个语句强制让condition返回0或者1.

1 - 2*!!(condition)
这个就是条件符合时,大小为0;,编译不报错;否则大小为-1,编译报错。

1;

这个语句不会产生额外的语句,但是会有编译时的警告

(void)1;
这个语句即使使用了 -Wall的编译参数,也不会有警告。

因此,BUILD_BUIG_ON这个宏展开后等效于

(void)sizeof(char[1])
或者

(void)sizeof(char[-1])






评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值