You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C/C++中用宏或模板生成带迭代编号的函数名?

结论先行

你的判断是正确的:普通运行时循环的迭代值无法传递给预处理器做标记拼接,因为预处理阶段执行在编译、运行阶段之前,运行时变量的值对预处理器完全不可见,因此直接用「简单宏+运行时循环」的方案确实走不通。


方案1:X宏(X Macro)方案(C/C++通用,无版本要求)

这是处理这类批量重复代码最常用的预处理方案,只需要维护一份中断号列表,就能自动生成所有声明和注册代码,全程没有重复逻辑:

  1. 先定义统一的中断列表宏:
// 所有需要注册的中断号都在这里加,后续不需要改其他代码
#define ISR_LIST \
  ISR_ENTRY(0) \
  ISR_ENTRY(1) \
  ISR_ENTRY(2) \
  ISR_ENTRY(3) \
  // 按需加更多
  1. 生成所有extern "C"声明:
#define ISR_ENTRY(n) extern "C" void interrupt_handler_##n();
ISR_LIST
#undef ISR_ENTRY
  1. 生成批量注册逻辑:
void func() {
#define ISR_ENTRY(n) setup_isr(n, interrupt_handler_##n);
  ISR_LIST
#undef ISR_ENTRY
}

如果后续要新增中断,只需要在ISR_LIST里加一行ISR_ENTRY(xxx)即可,不需要修改其他位置的代码。


方案2:C模板方案(C11及以上可用)

如果你的项目可以用现代C++特性,可以结合编译期序列实现批量注册,类型安全性更高,也方便加额外的编译期校验逻辑:

  1. 先做一个编译期的中断处理函数数组(可以结合上面的X宏生成数组内容,避免重复手写):
// 也可以用X宏生成这个数组的初始化列表,避免手写
constexpr void (*isr_handlers[])() = {
  interrupt_handler_0,
  interrupt_handler_1,
  interrupt_handler_2,
  // 更多handler
};
  1. 用std::index_sequence做编译期展开:
#include <utility>

template <std::size_t... Is>
void batch_setup_isr(std::index_sequence<Is...>) {
  // C++17及以上用折叠表达式,C++11可以用模板递归实现展开
  (setup_isr(Is, isr_handlers[Is]), ...);
}

void func() {
  // 比如要注册0~19共20个中断,直接传入对应长度的index_sequence即可
  batch_setup_isr(std::make_index_sequence<20>());
}

如果是C++11版本不支持折叠表达式,把batch_setup_isr改成模板递归的写法即可,逻辑是完全一致的。


内容的提问来源于stack exchange,提问作者Xcode23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 00:15:03