c语言中“##”的“token粘连”典型应用实例

📅 2026/6/27 22:33:52
c语言中“##”的“token粘连”典型应用实例
最近我在看linux内核源码看到使用“##”(token粘连)的一个比较经典的应用因为代码作者定义了一个含参宏将一系列内容基本完全相同的一些列函数进行了简化这样提高了代码可读性降低了代码重复性减少了代码行数。下面是具体内容1宏定义#define INPUT_DEV_CAP_ATTR(ev, bm) \ static ssize_t input_dev_show_cap_##bm(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ struct input_dev *input_dev to_input_dev(dev); \ int len input_print_bitmap(buf, PAGE_SIZE, \ input_dev-bm##bit, ev##_MAX, \ true); \ return min_t(int, len, PAGE_SIZE); \ }首先我们分析宏定义可以这里其实是静态函数定义宏定义的参数使用了##token粘连组成函数名以及函数内部子函数调用的参数这样的好处就是灵活传参不同能形成不同的函数名以及不同的函数内容。顺便说一句宏参数中evevent事件bmbitmap位图。还有一个现象##token粘连的前或者后面的令牌是宏的参数这个可以观察注意一下不然就失去了可变性。2宏调用INPUT_DEV_CAP_ATTR(EV, ev); INPUT_DEV_CAP_ATTR(KEY, key); INPUT_DEV_CAP_ATTR(REL, rel); INPUT_DEV_CAP_ATTR(ABS, abs); INPUT_DEV_CAP_ATTR(MSC, msc); INPUT_DEV_CAP_ATTR(LED, led); INPUT_DEV_CAP_ATTR(SND, snd); INPUT_DEV_CAP_ATTR(FF, ff); INPUT_DEV_CAP_ATTR(SW, sw);宏调用因为传递给宏的参数不同因此在预处理阶段就完成参数替代并展开形成并定义了不同函数。猜想源码作者意图。因为作者发现需要写一系列函数名、函数体内容基本相同只是存在局部不同的函数。如果直接写代码整个偏长而且有注水的嫌疑因此作者直接定义了一个含参宏来代表着一系列函数通过宏参数调用的方式实现了不同函数的定义。局部不一样的地方例如函数名函数体内部子函数调用传参值使用了“##”token粘连提高了灵活性并且最终实现了代码量减少降低了代码重复性。