6

Are there any significant benefits to using macros instead of static inline methods? In particular, how can one implement passing of varargs further down the call chain with static inline method which can be done in one step with a macro?

#define myprintf(fmt, args...) printf (fmt, args)

This is just a simple example but I'm still curious if there is an equivalent way of doing this using static inline without using va_args step.

Also is it always so that compiler inlines static inline methods? What about their size? What about calling arbitrary submethods? If I use several macros all of it compiles into a single expression and so it is probably easier for the compiler to optimize. Is compiler always smart enough to convert multiple levels of static inline calls into a single expression?

mafso
  • 5,433
  • 2
  • 19
  • 40
user2826084
  • 517
  • 5
  • 11
  • "Is compiler always smart enough ...?" It depends on the compiler. – Barmar Dec 14 '14 at 13:59
  • C99 has variable argument macros. – Crowman Dec 14 '14 at 15:49
  • I corrected the space in your code example. As it was written, `myprintf` wasn't a macro function and would be replaced by `(fmt, args...) printf (fmt, args)` where it appears. – mafso Dec 14 '14 at 16:27

1 Answers1

6

Are there any significant benefits to using macros instead of static inline methods?

Macros do not do type-checking, and do not evaluate their arguments, which brings great power and great danger.

So (to quote a well known example)

#define MAX(a,b) (a>b)?a:b

might seem like a better idea than

static inline int max(a,b) { return (a>b)?a:b; }

as it doesn't require an int argument (i.e. will work for all types that support the > operator), save for the fact that

  • It evaluates a or b twice (consider MAX(a++,b++))
  • It has the potential for operator precedence issues

This solves the second:

#define MAX(a,b) ((a)>(b)?(a):(b))

How can one implement passing of varargs further down the call chain with static inline method which can be done in one step with a macro?

C99 supports variadic macros, and gcc has (non-standard) extensions to this defined here.

In fact there are two formats:

#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)

where __VA_ARGS__ gets replaced by the variadic elements; this is standard C99.

gcc also provides:

#define debug(format, args...) fprintf (stderr, format, args)

where args can represent more than one argument.

In the first formulation, with gcc only, you can cope with the arguments being omitted completely and avoid a superfluous comma using the pasting macro operator ##, i.e.:

#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)

There is no standards-based way of achieving that.

[Does the] compiler [always] inline static inline methods?

No, the compiler is free to do what it wants. It can inline them, or produce one set of object code per compilation unit. However, at least in theory, it could do the same with #define'd macros. The compiler will not always convert multiple levels of inline macros into a single expression, as even a single inline macro may not in fact be coded inline; normally the compiler is smarter than the programmer in determining whether that is a good idea or not.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
abligh
  • 24,573
  • 4
  • 47
  • 84
  • `#define debug(...) fprintf(stderr, __VA_ARGS__)` can achieve the same effect here, without resorting to the gcc extensions. – Crowman Dec 14 '14 at 15:57
  • @PaulGriffiths your point is that the `...` thing without an argument is non-standard, `## __VA_ARGS__` is non-standard, but `__VA_ARGS__` alone is standard (as opposed to them all being a gcc extension)? I that that's right, and I will fix. – abligh Dec 14 '14 at 16:00
  • Yes, exactly, `__VA_ARGS__` is standard as of C99, but it requires you to provide at least one argument, so my example showed how to get the same effect as `## __VA_ARGS__` in a standards-based way. – Crowman Dec 14 '14 at 16:01
  • @PaulGriffiths indeed - fixed. – abligh Dec 14 '14 at 16:02