类似宏的功能,在体内有宏

Macro-like function with macros inside the body

提问人:Pararera 提问时间:11/6/2023 最后编辑:Pararera 更新时间:11/6/2023 访问量:73

问:

我正在尝试制作类似宏的函数,该函数将“创建”几行新宏。 ARM-GCC 预处理器对这种类似宏的函数不满意。如何在没有外部工具的情况下实现相同的功能的任何想法?

#define SML_DEBUG(_name) \
    #if defined(DEBUG_##_name) \
        #define _name##_LOG DEBUG_HANDLER \
    #else \
        #define _name##_LOG(...) \
    #endif

任务是为用于打印调试内容的函数创建宏。

例如,

#define DEBUG
#define DEBUG_HANDLER log
#define DEBUG_TEST // Enable debug prints for test module
#define SML_DEBUG(TEST) // Should create test_LOG macro or its placeholder if DEBUG build is disabled

void foo(void)
{
    TEST_LOG("Hello World\n"); // Will redirect to "log" function(defined by DEBUG_HANDLER)
}

错误是:

error: '#' is not followed by a macro parameter
  182 | #define SML_DEBUG(_name) \
      |                        ^

谢谢!

C-预处理器

评论

0赞 273K 11/6/2023
我从未见过这样的错误消息“预处理器不满意”。你能发布真正的 GCC 错误吗?
4赞 Eric Postpischil 11/6/2023
处理宏后,生成的源代码不会作为预处理器指令(如 、 和 )进行处理,即使它类似于预处理器指令。#if#else#endif
0赞 Pararera 11/6/2023
@273K 添加了,对不起。
1赞 Eric Postpischil 11/6/2023
您得到的具体错误是因为在类似函数的宏(不是类似宏的函数)中应该用作字符串化运算符,如 ,根据 C 2018 6.10.3.2 1。由于您有 ,并且不是参数名称,因此编译器会抱怨。(这是一个约束段落,因此编译器需要抱怨它。##define MakeString(x) #x#ifif
0赞 Pararera 11/6/2023
@EricPostpischil 知道如何躲避吗?唯一的方法是手动复制粘贴我需要的每个模块的正文。

答:

2赞 Eric Postpischil 11/6/2023 #1

您得到的具体错误是因为在类似函数的宏(不是类似宏的函数)中应该用作字符串化运算符,如 ,根据 C 2018 6.10.3.2 1。由于您有 ,并且不是参数名称,因此编译器会抱怨。(这是一个约束段落,因此编译器需要抱怨它。##define MakeString(x) #x#ifif

根据 C 2018 6.10.3.4 3,即使允许在宏替换列表中使用,处理宏生成的源代码也不会作为预处理器指令(例如 、 和 )进行处理。##if#else#endif

您可以有条件地定义宏,而不是尝试使用条件源代码定义宏:

#if defined DEBUG_TEST
    #define _TEST_LOG DEBUG_HANDLER
#else
    #define _TEST_LOG(...)
#endif

这意味着您需要为要启用/禁用日志记录的每个模块重复这些行,但这就是源代码编辑器和脚本语言的用途。并非所有事情都应该在 C 预处理器中完成。

评论

0赞 Pararera 11/6/2023
谢谢你的解释。我的类似函数的宏应该扩展到您编写的示例。只是为了更容易将调试日志记录添加到模块/驱动程序,因为我计划为多个级别(错误、警告、信息、详细)添加选项,所以复制粘贴似乎很讨厌。似乎我必须坚持 c/p 并重命名:|SML_DEBUG(TEST)
0赞 Pararera 11/6/2023
添加。这是结果