C 预处理器宏定义宏

问题描述 投票:0回答:7

你能用 C 中的宏做这样的事情吗?

#define SUPERMACRO(X,Y) #define X Y

then

SUPERMACRO(A,B) expands to #define A B

我有一种感觉,不是因为预处理器只通过了一次。

仅限官方海湾合作委员会。请不要使用第三方工具。

gcc c-preprocessor
7个回答
39
投票

宏不能扩展为预处理指令。从C99 6.10.3.4/3“重新扫描并进一步替换”:

生成的完全宏替换的预处理标记序列不会作为预处理指令进行处理,即使它类似于一个,


20
投票

您无法在其他宏中定义宏,但您可以从您的宏中调用宏,这可以获得基本相同的结果。

#define B(x) do {printf("%d", (x)) }while(0)
#define A(x) B(x)

所以,

A(y)
扩展为
do {printf("%d", (y)) }while(0)


4
投票

不。操作的顺序是在完成任何宏扩展之前识别所有预处理器指令;因此,如果宏扩展为看起来像预处理器指令的内容,则它不会被识别为预处理器指令,而是会被解释为(错误的)C 源文本。


3
投票

抱歉,你不能。您可以在宏中调用其他宏,但不能定义新的宏。


1
投票

您可以尝试仅使用预处理选项运行它,然后使用预处理文件进行编译。


0
投票

好吧,这是一个疯狂不守规矩的本土 cpp 程序员和另一位程序员。优雅的程序员不愿意在循环体内使用终止条件,但我非常不同意。我用我比普通程序员更多地使用循环这一事实来证明我的信念,因为我手动进行文本解析,而不是使用正则表达式。再加上我需要循环的其他情况。所以我理解循环内终止条件的需要。事实上,即使我只有一个条件,我可能更喜欢 while(true) 循环;为了在循环体内执行我的所有代码。例如:

while(true)
{
    if(condition)
    {
     // do something
     return;
    }

    // .... long body
}

这种格式允许人们立即查看循环终止时采取的操作。

无论如何,我会解释一下BREAK_OUT_OF关键字。它允许您从内部循环或 switch 语句中跳出外部循环或 switch 语句。该关键字设置为在 cpp 的下一版本(cpp 2026)中出现。但不用担心,现在您可以在原始 cpp 编译器中模拟它。步骤如下。

第1步:使用以下命令下载BREAK_OUT_OF关键字包:

#define BREAK_OUT_OF(ID) goto STATEMENT##ID
#define S_ID(ID)
#define DEF_S_ID(ID) STATEMENT##ID:

不要被命令中的 goto 语句所迷惑。这不是我们都讨厌的常规 goto 语句。它是变相的 jmp 语句。

第2步:现在您已经下载了兼容包;当您需要从内部语句中跳出外部语句时;你首先给它一个ID。您可以使用 S_ID 关键字来执行此操作。

while(true) S_ID(first_loop)

第 3 步:将 DEF_S_ID 关键字紧接在语句主体之后。请注意,在即将到来的 cpp 26 中,这将自动为我们完成。

while(true) S_ID(first_loop)
{
}DEF_S_ID(first_loop)

最后一步:使用 BREAK_OUT_OF 关键字从内循环中跳出外循环

while(true) S_ID(first_loop)
{
    switch(10) S_ID(1)
    {
     case 10: BREAK_OUT_OF(first_loop);
     case 0: BREAK_OUT_OF(1);
    }DEF_S_ID(1)
}DEF_S_ID(first_loop)

-1
投票

不过你可以这样做: #define SUPERMACRO(X,Y) 定义 X Y

然后您可以使用编辑器的宏扩展功能并粘贴缺少的#。

甚至更好:使用不同的、更强大的字符串处理语言作为预处理器。

© www.soinside.com 2019 - 2024. All rights reserved.