Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C Macro with varargs

Tags:

c

I am trying to write a macro which returns the smallest value of several integers. When I compile the following code, it throws an error "expected expression". I don't know what's wrong there. Could anyone point out the issues with this code?

#define SMALLEST (nums, (ret_val), ...)          \
do {                                             \
    int i, val;                                  \
    va_list vl;                                  \
    va_start(vl,nums);                           \
    (*ret_val) = va_arg(vl, int);                \
    for (i = 1; i < nums; i++)                   \
    {                                            \
        val=va_arg(vl, int);                     \
        if ((*ret_val) > val)                    \
            (*ret_val) = val;                    \
    }                                            \
    va_end(vl);                                  \
} while(0)

int main ()
{
  int nums = 3;
  int ret_val = 0;
  SMALLEST(nums, &ret_val, 1, 2, 3);
  return 0;
}

I am just curious about how to do it with Macro.

like image 619
Zack Avatar asked Dec 06 '22 22:12

Zack


2 Answers

I am just curious about how to do it with Macro.

You can't. va_list is a way for a variadic function to access its arguments. What you have written is a variadic macro. They are not the same (in particular the variadic macro is still only a syntactic convenience that does not let you process individual arguments). The only way to do what you want is to call a variadic function of your own design inside the variadic macro (and then you might as well eliminate the macro).

However, if you really insist on using a variadic macro, it turns out that you are lucky that the same separator , is used in macro arguments and in array initializers, so you can try something like:

#define F(X, ...) \
  do { \
    int t[] = { __VA_ARGS__ }; \
    for (int i = 0; i < sizeof t / sizeof t[0]; i++) \
      … \
  } while (0)
like image 155
Pascal Cuoq Avatar answered Dec 28 '22 16:12

Pascal Cuoq


I don't think you can. From the gcc manual (https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html) the best you can do in a standard way is write __VA_ARGS__, which will expand the arguments in place (for example to pass to a function).

It then goes on to define other non-standard extensions, which you might be able to use, but wouldn't be standard.

Why not do it with a function?

like image 25
DavidW Avatar answered Dec 28 '22 16:12

DavidW