Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

which is undefined (see EXP30-C, ". Do not depend on order of evaluation between sequence points").

Compliant Solution

When the macro definition is replaced by an inline function, the side effect is executed only once before the function is called.

...

Wiki Markup
In this noncompliant code example, the programmer has written a macro called {{EXEC_BUMP()}} to call a specified function and increment a global counter \[[Dewhurst 02|AA. C References#Dewhurst 02]\].  When the expansion of a macro is used within the body of a function, as in this example, identifiers refer to the declarations in scope where the body occurs.  As a result, when the macro is called in the {{aFunc()}} function, it inadvertently increments a local counter with the same name as the global variable. Note that this example violates [DCL01-C,. "Do not reuse variable names in subscopes]."

Code Block
bgColor#FFCCCC
size_t count = 0;

#define EXEC_BUMP(func) (func(), ++count)

void g(void) {
  printf("Called g, count = %zu.\n", count);
}

void aFunc(void) {
  size_t count = 0;
  while (count++ < 10) {
    EXEC_BUMP(g);
  }
}

...

This noncompliant code example also violates EXP30-C, ". Do not depend on order of evaluation between sequence points."

Compliant Solution

The execution of functions, including inline functions, cannot be interleaved, so problematic orderings are not possible.

...

An example of the use of function-like macros to create type-generic functions is shown in MEM02-C, ". Immediately cast the result of a memory allocation function call into a pointer to the allocated type."

Type-generic macros may also be used, for example, to swap two variables of any type, provided they are of the same type.

...