谨防define宏陷阱

本文通过一个实际案例揭示了宏定义在C/C++编程中可能引入的陷阱。作者在实现重复数据删除(Deduplication)存储技术的过程中,由于宏定义BLOCK_LEN缺少括号,导致计算出的block_num远超预期值。此经历强调了正确使用宏定义的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在研究Deduplication(重复数据删除)存储技术,实现一个dedup原型系统,结果在Coding中遇到了一个莫名其妙的问题。简略代码如下:

#include "dedup.h" #ifndef BLOCK_LEN #define BLOCK_LEN 32 * 1024 /* 32K Bytes */ #endif #define BACKET_SIZE 10240 ... int fd_src, fd_dest; char buf[BLOCK_LEN] = {0}; unsigned int rwsize, pos, block_id; unsigned char md5_checksum[16] = {0}; unsigned int *metadata = NULL; unsigned int block_num = 0; struct stat stat_buf; hashtable *htable = NULL; dedup_file_header dedup_hdr; ... if (-1 == (fd_src = open(argv[1], O_RDONLY))) { perror("open source file"); return errno; } ... htable = create_hashtable(BACKET_SIZE); if (NULL == htable) { perror("create_hashtable"); return errno; } pos = 0; block_id = 0; if (-1 == fstat(fd_src, &stat_buf)) { perror("fstat source file"); goto _EXIT; } block_num = stat_buf.st_size / BLOCK_LEN; metadata = (unsigned int *)malloc(sizeof(unsigned int) * block_num); if (metadata == NULL) { perror("malloc metadata"); goto _EXIT; }

我用大小为1.9MB的文件作为源文件,结果 block_num 居然为 61881344,真是出乎想像。块大小BLOCK_LEN = 32KB,所以block_num应该为59才对。问题出在哪了呢?这段代码非常简单了,没有什么复杂的逻辑,我反复review了几次也没有发现问题。于是,在家里转了两圈,然后无意中注意到了BLOCK_LEN的宏定义。define总是容易犯些低级的错误,难道我也犯了最低级的错误不成?

#define BLOCK_LEN 32 * 1024 /* 32K Bytes */

看到这行,我当时就傻了,自己还真犯了最低级、最原始的错误。

block_num = stat_buf.st_size / BLOCK_LEN;

上面这行宏替换后就成了:

block_num = stat_buf.st_size / 32 * 1024;

终于明白问题出在何处了,给宏加上(),即#define BLOCK_LEN (32 * 1024) ,一切OK了!

这次经验教训深刻,估计我以后很少会再犯类似错误了,另外也小有收获和乐趣 ^-^。

最后提醒一下:宏使用很方便,但要谨慎使用,尤其需要注意书写格式,尽量多用括号避免歧义。细节是魔鬼!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值