6

How do I pass macro arguments along with another integer variable to a macro function?

#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;
}

I expect the output to be:

Sum: 3
Macro Sum: 6

However, I get the following error:

main.c:18:41: error: macro "SUM" requires 3 arguments, but only 2 given
     printf("\nMacro Sum: %d", SUM(FOO, a));
1
  • When you expand that line using SUM(FOO, a), FOO is not expanded until after the arguments have been determined. There are only 2 arguments, but the macro expects 3 — hence the message. The expansion of FOO into 1, 2 would happen next. Commented Dec 3, 2017 at 4:57

2 Answers 2

5

Macro arguments are not expanded when the macro call is parsed. After the macro call is parsed, each use of a macro parameter in the macro definition text is replaced with the macro-expanded argument, except for macro parameters used with the # or ## operations (stringify and token paste), which are replaced with the unexpanded text of the macro argument. Then the # and ## operations are performed, and then the entire macro body is scanned one more time.

The consequence is that SUM(FOO, a) is parsed aa having two arguments. Since the macro requires three, thatvwon't compile.

You can work around this, to some extent, by using one extra level of macro expansion:

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

printf("\nMacro Sum: %d", CALL(SUM, FOO, a));

Now the use of the __VA_ARGS__ parameter (which happens to be a varargs parameter, although that makes absolutely no difference to the expansion order) will be expanded before the replacement text is rescanned, so FOO will be invoked with three arguments.


By the way, outputting a newline character at the beginning of an output line is a bad habit which will get you into trouble someday. Output lines should have a newline at the end of the line:

printf("Macro Sum: %d\n", CALL(SUM, FOO, a));

There is nothing wrong with also writing a blank line beforehand by putting a newline at the beginning as well, but regardless, you should almost always terminate outpur lines with the \n. Otherwise:

  1. The line might not be written immediately. Line-buffered output is not actually sent to the output device/file until a newline is sent.

  2. If the program is a console app and it terminates without properly closing stdout, you will find yourself typing the next shell command at rhe end if the last output line. This tends to confuse line-editing input libraries like readline.

Sign up to request clarification or add additional context in comments.

Comments

0

Single macro argument would work:

#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;
}

Output:

Sum: 3
Macro Sum: 6

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.