謹防define巨集陷阱

2021-08-24 22:36:53 字數 1303 閱讀 3574

最近在研究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] = ; unsigned int rwsize, pos, block_id; unsigned char md5_checksum[16] = ; 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))) ... htable = create_hashtable(backet_size); if (null == htable) pos = 0; block_id = 0; if (-1 == fstat(fd_src, &stat_buf)) block_num = stat_buf.st_size / block_len; metadata = (unsigned int *)malloc(sizeof(unsigned int) * block_num); if (metadata == null)

我用大小為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了!

這次經驗教訓深刻,估計我以後很少會再犯類似錯誤了,另外也小有收穫和樂趣 ^-^。

關於巨集 define使用陷阱總結

巨集定義發生在預編譯階段,簡單的說本質就是文字替換。使用時,有以下注意事項 1,用巨集定義表示式時,要使用完備的括號 如一下三個例子 define add a,b a b define add a,b a b define add a,b a b 這三種定義,全部都是不符合要求的。陷阱如下 在計算a...

define 巨集 替代巨集

編寫 時經常要定義常量 static const nstimeinterval kanimationduration 0.3 複製 使用型別變數,可以清楚地描述常量的含義,以及它的型別。命名法 若常量侷限於某 編譯單元 translation unit,也就是實現檔案,m檔案 之內,則在前面加字母k...

define 巨集 替代巨集

編寫 時經常要定義常量 static const nstimeinterval kanimationduration 0.3 複製 使用型別變數,可以清楚地描述常量的含義,以及它的型別。命名法 若常量侷限於某 編譯單元 translation unit,也就是實現檔案,m檔案 之內,則在前面加字母k...