首页 文章

Variadic宏参数计数不能按预期工作

提问于
浏览
1

所以,基本上我正在尝试实现一个宏来计算 VA_ARGS 中的参数数量 .

为简单起见,它最多只能工作3个参数 . 问题是当宏使用少于3个参数时,它不起作用,并触发“预期表达式”错误 .

#define EXPAND( x ) x
#define PP_NARG(...) EXPAND(PP_ARG_N(__VA_ARGS__, PP_RSEQ_N()))
#define PP_ARG_N(_1, _2, _3, N,...) N
#define PP_RSEQ_N() 3,2,1,0

void main()
{
    printf("\nTEST PP_NARG: %i", PP_NARG());        //Doesn't work (in this case it shouldn't work, so it's correct)
    printf("\nTEST PP_NARG: %i", PP_NARG(0));       //Doesn't work
    printf("\nTEST PP_NARG: %i", PP_NARG(0,0));     //Doesn't work
    printf("\nTEST PP_NARG: %i", PP_NARG(0,0,0));   //Works
}

保持正常工作的线路正确编译并打印“TEST PP_NARG:3” .

我认为问题可能是PP_RSEQ_N()由于某种原因只扩展到“3”而不是“3,2,1,0”,因为即使PP_RSEQ_N()被定义为此

#define PP_RSEQ_N() 10,9,8,7,6,5,4,3,2,1,0

它仍然不能用少于3个参数 .

我使用MSVC编译器,它可能是问题的原因,因为它与宏的表现不太好,如下所示:MSVC doesn't expand VA_ARGS correctly

1 回答

  • 2

    在您的实现中 PP_RSEQ_N()PP_ARG_N 的参数 . 作为一个参数,它只在预处理的参数替换阶段进行了扩展,但只是在替换替换列表中的参数之前发生(只要在替换列表中,它没有被字符串化并且没有参与糊) .

    由于 PP_ARG_N 在其替换列表中只有第四个参数 NPP_RSEQ_N() 只会在你碰巧传入三个参数时才会展开 . (在重新扫描和替换阶段进行第二次扫描,这适用于参数替换后......但是这里没有效果,因为在电话中提到了 PP_RSEQ_N() ) .

    摆脱这个宏,并把它放在 PP_NARG 像这样:

    #define EXPAND( x ) x
    #define PP_NARG(...) EXPAND(PP_ARG_N(__VA_ARGS__, 3,2,1,0))
    #define PP_ARG_N(_1, _2, _3, N,...) N
    

    ......事情“工作”很好:

    PP_NARG() 扩展为 1
    PP_NARG(x) 扩展为 1
    PP_NARG(x,y) 扩展为 2

    但请注意, PP_NARG() 实际上并不正确;对于预处理器,这不是传递零参数 . 它's passing one argument that is just empty. It'与 #define X(A) OPEN A CLOSE / X() 产生 OPEN CLOSE 相同 . 如果由于某种原因你想要将它扩展到0,可能会有一些想要实现这一点,但对于这个答案,我只专注于让你超过这一个驼峰 .

相关问题