-5

I have read from several authors that macros in C should be avoided whenever possible, and use inline functions instead. It's true that inline only 'requests' the compiler to replace the function call by 'expand' the function body in the calling place, however my understanding is that, if a modern C compiler 'doesn't want to inline' a function, probably it's because it shouldn't be.

However, I still see an intensive use of macros and #ifdef etc. directives in 'modern' open source projects, such as FreeRTOS, Zephyr and many others.

Does this mean that the industry has reconsidered its position with regards to macros? Is there any good reason to use macros instead of inline functions?

4

2 Answers 2

4

You see an absolute rule, and things don't work that way. You also seem to be focussed on macros vs. inline functions which is very rarely the question.

Macros can be extremely useful if you know how to use them. They can also be anything from misleading to dangerous if you don't know what you're doing.

I haven't used the two projects that you mention, but I have used others, and their use of macros is generally very reasonable and appropriate. The stupid macro uses what we are warned not to use are very rare. "Use inline functions instead of macros" is a bit outdated - I'd suggest using real functions instead of macros for that and only use macros when performance is absolutely critical (which is rare).

-3

Common usages of macros

Macro for defining constants

// Bad
#define PI 3.14

// Good
const double PI = 3.14;

Always use const instead. This makes sure that you explicitly type your constant.

Function-like macro

If you can use function to achieve what you want, always use a function. Explicitly declaring this function inline is not necessary. As you correctly noted, the inline keyword does not really tell compiler to inline the function. It just puts a restriction on the function that you can not take address of that function. Practically, this allows you to put the function body in the header file without compiler giving you a redefinition error when you include this header in multiple C files.

Where is a function-like macro actually useful?

There are some cases where you want to remove duplication of certain code and a function-call does not let you achieve what you want.

For example a logging macro that prints line number and function name.

// Macro definition in some header file.
#define MYLOG(fmt, args...) \
fprintf(stderr, "%s:%d, " fmt "\n", __func__, __LINE__, ##args);

// Usage
{
...

MYLOG("Hello World %d", 1234);
...
}

This creates a function-like macro that prints your message along with the function name and line-number from the source file. As an exercise try to see if you can avoid using a macro and achieve the same functionality.

P.S. It's not possible (at least in C or C++).

Macros as compile-time flags

This is a very genuine and justified usage of macros. If you want to do selective compilation based on some conditions (which come from either compiler command line or a Makefile), there is no other way than to use macros. However, even in this scenarios macros should be used sparingly. Having too many #ifdefs in your code makes it difficult to read. As much as possible, I would do this selective compilation by moving code to separate files.

10
  • 2
    No, there are cases for coding #ifdef PI. Look into the source code of GCC for examples and see GNU autoconf Jul 2, 2020 at 4:34
  • There may be existing code that uses this pattern and but for new code there is very little justification of #defining constants.
    – Punit Soni
    Jul 2, 2020 at 5:17
  • 1
    There are lots of good reasons for #defineing constants. Look into the source code of the Linux kernel as a counter example, and also inside the source code of SBCL or of GCC Jul 2, 2020 at 5:22
  • 1
    A good reason to use #define for constants in C is when the compiler needs to use the value (for example, as an array size). In C, const does not mean constant, but rather read-only and a const variable can't be used where a true constant is required. Jul 2, 2020 at 8:02
  • 1
    const double PI = 3.14; restricts PI to the precision of double. #define PI 3.14 allows PI to have the precision of long double when FLT_EVAL_MODE = 2. Not functionally equivalent code between the macro and const. Best use depends on case. Jul 2, 2020 at 21:12

Not the answer you're looking for? Browse other questions tagged or ask your own question.