【问题标题】:Macro-producing macros in C?用 C 语言生成宏?
【发布时间】:2009-05-13 20:35:59
【问题描述】:

我想让 C 预处理器为我生成宏(即,我只使用 C99)。我会写一个宏

#define make_macro(in) <...magic here...>

当我放的时候

make_macro(name1)
make_macro(name2)

在后面的代码中,它会扩展为

#define name1(...) name1_fn(name1_info, __VA_ARGS__)
#define name2(...) name2_fn(name2_info, __VA_ARGS__)

然后我就可以使用 name1 和 name2 作为(宏实现的)函数。我认为我在这两个步骤中都无法使用宏:使用宏重复重新填充模板是有意义的,并且可变参数处理除了通过宏之外将不起作用。

那么,<...magic here...> 占位符中的内容是什么?在这一点上,我开始相信这在 C99 中是不可能的,但也许我遗漏了一些语法细节。

【问题讨论】:

  • 为什么是宏?我没有得到这个“反复重新填充模板”的观点。什么模板,什么补充?

标签: c macros c-preprocessor variadic-functions


【解决方案1】:

这在标准 C 中是不可能的。

【讨论】:

    【解决方案2】:

    您是否考虑过使用 M4 宏? 我认为它们在大多数平台上都可用,所以这不应该是一个限制。

    M4 GNU page

    【讨论】:

    • +1 ,M4 经常被忽视,是一个非常强大的代码生成工具。不过,我希望人们每次看到我使用 LISP 笑话时都会停下来。
    【解决方案3】:

    正如大家所说,你不能完全按照你的要求去做。

    你可以通过强制 C 预处理器运行两次来做类似的事情,例如,在 makefile 中使用这样的规则:

    .c.pp:
       $(CPP) $< -o $@
    

    然后将您的文件扩展名为 test.pp。 Makefile 会运行一次生成 .c 文件,然后在 .c 文件上正常运行会运行第二次。

    就个人而言,我宁愿用 Perl 或其他东西编写一个外部脚本来为我生成 C 代码;它比使用 C 预处理器玩游戏要干净一些。这取决于我们在谈论多少代码。

    【讨论】:

    • 聪明,但我感觉在 CPP 的输出上运行 CPP 可能会导致编译指示和行号等行出现问题。
    【解决方案4】:

    这是不可能的,因为宏只执行一次。

    这并不意味着你不能在你的宏中使用其他宏,但你不能这样做

    #define TEST #define HALLO 33
    
    int x = TEST;
    

    然后期望 x 为 33! 你会得到一个语法错误,因为你尝试过

    int x = #define HALLO 33;
    

    或者编译器可能已经在#define 中抱怨#define。

    【讨论】:

      【解决方案5】:

      根据C99 Section 6.10.3.2

      类函数宏的替换列表中的每个 # 预处理标记应为 后跟一个参数作为替换列表中的下一个预处理标记。

      因此,如果您有一个名为 define 的参数,您当然可以将 #define 放入宏中,但它永远不会满足您的要求。这经常困扰我,因为我必须在 C 中工作,因此不能使用 C++ 模板。

      【讨论】:

        【解决方案6】:

        试试#define make_macro(name,...) name##_fn(name##_info, __VA_ARGS__)

        这样使用:

        make_macro(name1)
        make_macro(name2,1)
        

        这会产生

        name1_fn(name1_info)
        name2_fn(name2_info,1)
        

        【讨论】:

          猜你喜欢
          • 2010-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多