如何实现对__VA_ARGS__的每个参数调用指定宏?
实现对__VA_ARGS__每个参数调用指定宏的方法
要让M_ALL宏对每个可变参数调用M宏,可借助C预处理器特性实现,以下是两种可行方案:
方案一:使用C20标准的__VA_OPT__(推荐)
该方案简洁直观,依赖C20及以后的标准支持:
#define M(x) do { x++; f(x); } while(0) // 辅助宏:对单个参数调用M并添加分号 #define M_EACH_PARAM(x) M(x); // 主宏:展开所有可变参数,逐个调用M_EACH_PARAM #define M_ALL(...) do { \ __VA_OPT__(M_EACH_PARAM(__VA_ARGS__)) \ } while(0)
当调用M_ALL(x, y, z)时,预处理器会展开为:
do { do { x++; f(x); } while(0); do { y++; f(y); } while(0); do { z++; f(z); } while(0); } while(0)
__VA_OPT__的作用是当可变参数非空时才展开括号内的内容,避免空参数时产生多余分号。
方案二:兼容旧标准的递归宏展开
如果需要兼容C11及更早的标准,可以使用递归宏方式:
#define M(x) do { x++; f(x); } while(0) // 递归终止标记 #define M_REC_END() // 递归展开宏:处理第一个参数,再递归处理剩余参数 #define M_EXPAND(x, ...) M(x); __VA_ARGS__ M_REC_END() // 主宏:包裹递归展开逻辑 #define M_ALL(...) do { \ M_EXPAND(__VA_ARGS__, M_REC_END()) \ } while(0)
调用M_ALL(x, y, z)时,会逐层递归展开,最终得到与方案一相同的结果。这种方式通过递归逐个处理参数,直到触发终止标记。
内容的提问来源于stack exchange,提问作者Abdulmalek Almkainzi
相关产品推荐
相关产品推荐

