【问题标题】:Macro count params宏计数参数
【发布时间】:2012-12-18 19:14:40
【问题描述】:

为了让编译器满意,我必须计算传递给A() 的参数,否则当pedantic 标志打开并且只传递一个参数时,gcc 会引发“warning: ISO C99 requires rest arguments to be used

#include <stdio.h>

/* Count params */
#define N_ARGS(...) N_ARGS_IMPL(__VA_ARGS__,n,n,n,n,n,n,n,n,n,1,1)
#define N_ARGS_IMPL(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) N

#define A_fmt_void
#define A_arg_void

/* link */
#define A_fmt_link_1(fmt) " href=\""fmt"\""
#define A_fmt_link_n(fmt, ...) " href=\""fmt"\""
#define A_fmt_link_N(n, ...) A_fmt_link_##n(__VA_ARGS__)
#define A_fmt_link_X(n, ...) A_fmt_link_N(n,__VA_ARGS__)
#define A_fmt_link(...) A_fmt_link_X(N_ARGS(__VA_ARGS__), __VA_ARGS__)

#define A_arg_link_1(fmt)
#define A_arg_link_n(fmt, ...) , __VA_ARGS__
#define A_arg_link_N(n, ...) A_arg_link_##n(__VA_ARGS__)
#define A_arg_link_X(n, ...) A_arg_link_N(n,__VA_ARGS__)
#define A_arg_link(...) A_arg_link_X(N_ARGS(__VA_ARGS__), __VA_ARGS__)

/* text */
#define A_fmt_text_1(fmt) fmt
#define A_fmt_text_n(fmt, ...) fmt
#define A_fmt_text_N(n, ...) A_fmt_text_##n(__VA_ARGS__)
#define A_fmt_text_X(n, ...) A_fmt_text_N(n,__VA_ARGS__)
#define A_fmt_text(...) A_fmt_text_X(N_ARGS(__VA_ARGS__), __VA_ARGS__)

#define A_arg_text_1(fmt)
#define A_arg_text_n(fmt, ...) , __VA_ARGS__
#define A_arg_text_N(n, ...) A_arg_text_##n(__VA_ARGS__)
#define A_arg_text_X(n, ...) A_arg_text_N(n,__VA_ARGS__)
#define A_arg_text(...) A_arg_text_X(N_ARGS(__VA_ARGS__), __VA_ARGS__)

/* macro */
#define A(link, text) \
    printf("<a"A_fmt_##link">"A_fmt_##text"</a>\n" A_arg_##link A_arg_##text)

int main(void)
{
    A(link(), void);
    A(void, text());
    A(link("http://www.google.es"), void);
    A(link("%s/%s", "http://www.google.es", "home"), text("Visit google"));
    A(void, text("%s today", "Visit google"));
    A(link("http://%s/%s", "www.google.es", "home"), text("%s today", "Visit google"));
    A(void,void);
    return 0;
}

通过N_ARGS 的这种实现,我只能使用 10 个参数,是否有另一种方法可以检查宏中是否有多个无限制的参数?

我知道, ## __VA_ARGS__ gcc 扩展,但我想避免警告

【问题讨论】:

  • 应该是编译器让你开心,而不是相反。
  • 这听起来像是一个 XY 问题,你做了什么让编译器首先发出警告?
  • @StoryTeller using (fmt, ...) 只有一个参数:警告:ISO C99 要求在使用, ## __VA_ARGS__ gcc 扩展时使用 pedantic 标志时使用其余参数

标签: c gcc c-preprocessor variadic-macros


【解决方案1】:

最后我用__ extension__修复了

#include <stdio.h>

#define A_fmt_void
#define A_arg_void
#define A_fmt_link(fmt, ...) " href=\""fmt"\""
#define A_arg_link(fmt, ...) , ## __VA_ARGS__
#define A_fmt_text(fmt, ...) fmt
#define A_arg_text(fmt, ...) , ## __VA_ARGS__
#define A(link, text) \
    __extension__ printf("<a" A_fmt_##link ">" A_fmt_##text "</a>\n" A_arg_##link A_arg_##text)

int main(void)
{
    A(
        link("%s", "http://wwww.google.com"),
        text("%s", "Visit google")
    );
    A(
        link("http://wwww.google.com"),
        void
    );
    A(
        void,
        text("Visit google")
    );
    A(
        void,
        void
    );
    return 0;
}

这可以防止在 pedantic flag 开启时出现警告 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    相关资源
    最近更新 更多