cmacros

(C) macro that contains 2 args in macro doesn't compile, but it works well in function. I want to know why. Thanks


I tried to optimize my code using macro, but it doesn't compile in some sentences. For simplification, I writed codes below to describe what I want to work out:

#define MACRO(x, y) ((x) + (y))
#define X 2,3

int fun(x, y)
{
    return x+y;
}

int main(void)
{
    int res;
    res = fun(X);   //ok
    res = MACRO(X); //**error:macro "MACRO" requires 2 arguments, but only 1 given**
    printf("%d\n", res);
    return 0;
}

I used to believe that macros simply replace words so it's no problem to do this, but now I think I was wrong. :(

More accurately: I was tring to do something like:

//global.h
#define MACRO(brief, num) fun(__LINE__, brief, num)

//test.c
#include <global.h>
#define X "brief",3

void fun(int line_num, char* brief, int num)
{
    printf("%d, %s,%d\n", line_num, brief, num);   //do something
}

int main(void)
{
    fun(__LINE__, X);  //ok
    MACRO("brief",3);   //ok
    MACRO(X);   //error: macro "MACRO" requires 2 arguments, but only 1 given
    return 0;
}

So I need to use this type of macro to reduce args.

I searched everywhere yesterday but nothing was found, I hope I could receive answers here.


Solution

  • You can use the variable arguments facility of the preprocessor, as in the following example (available on IdeOne):

    #include <stdio.h>
    
    #define MACRO(...)                MACRO_IMPLEMENTATION(__VA_ARGS__)
    #define MACRO_IMPLEMENTATION(x,y) ((x)+(y))
    
    #define X                         2,3
    
    int main (void) {
      printf ("MACRO (X)   = %d\n", MACRO (X));
      printf ("MACRO (2,3) = %d\n", MACRO (2,3));
      return 0;
    }
    

    The output is

    MACRO (X)   = 5
    MACRO (2,3) = 5
    

    The definition of MACRO takes a variable number or arguments, which are bound to __VA_ARGS__ (see section 6.10.3 in the standard). The definition of MACRO calls MACRO_IMPLEMENTATION which now sees two arguments either because MACRO was called with two or because it was called with an argument which expands to a list of two arguments.