将宏参数传递给宏函数

Hee*_*esh 6 c macros arguments function parameter-passing

如何将宏参数与另一个整数变量一起传递给宏函数?

#define SUM(X, Y, Z) X + Y + Z
#define FOO 1, 2

void print(int a, int b)
{
    printf("Sum: %d", a + b);
}

int main(void) 
{
    // Normal function works as expected
    print(FOO);

    // Macro function not working
    int a = 3;
    printf("\nMacro Sum: %d", SUM(FOO, a));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我期望输出是:

Sum: 3
Macro Sum: 6
Run Code Online (Sandbox Code Playgroud)

但是,我收到以下错误:

main.c:18:41: error: macro "SUM" requires 3 arguments, but only 2 given
     printf("\nMacro Sum: %d", SUM(FOO, a));
Run Code Online (Sandbox Code Playgroud)

ric*_*ici 5

解析宏调用时,不会扩展宏参数。解析宏调用后,宏定义文本中每次使用宏参数都将替换为宏扩展参数,但与 or#操作##(字符串化和标记粘贴)一起使用的宏参数除外,这些宏参数将替换为未扩展的文本的宏观论证。然后进行###运算,然后再对整个宏体进行一次扫描。

结果是SUM(FOO, a)解析 aa 有两个参数。由于该宏需要三个,因此无法编译。

在某种程度上,您可以通过使用一层额外的宏扩展来解决这个问题:

#define CALL(macro, ...)  macro(__VA_ARGS__)

printf("\nMacro Sum: %d", CALL(SUM, FOO, a));
Run Code Online (Sandbox Code Playgroud)

现在,参数的使用__VA_ARGS__(恰好是一个可变参数参数,尽管这对扩展顺序完全没有影响)将在重新扫描替换文本之前扩展,因此FOO将使用三个参数进行调用。


顺便说一句,在输出行的开头输出换行符是一个坏习惯,有一天会给你带来麻烦。输出行的末尾应有一个换行符:

printf("Macro Sum: %d\n", CALL(SUM, FOO, a));
Run Code Online (Sandbox Code Playgroud)

通过在开头放置一个换行符来预先编写一个空行并没有什么问题,但无论如何,您几乎应该始终以\n. 否则:

  1. 该行可能不会立即写入。在发送换行符之前,行缓冲输出实际上不会发送到输出设备/文件。

  2. 如果程序是一个控制台应用程序并且它在没有正确关闭的情况下终止stdout,您会发现自己在最后一个输出行的末尾键入下一个 shell 命令。这往往会混淆行编辑输入库,例如readline.


sg7*_*sg7 0

单个宏参数可以工作:

#define SUM(X, Y, Z) X + Y + Z
#define FOO1 (1) 
#define FOO2 (2)

void print(int a, int b)
{
    printf("Sum: %d", a + b);
}

int main(void) 
{
    // Normal function works as expected
    print(FOO1,FOO2);  

    int a = 3;
    printf("\nMacro Sum: %d", SUM(FOO1, FOO2, a));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

Sum: 3
Macro Sum: 6
Run Code Online (Sandbox Code Playgroud)