Versions Compared

Key

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

...

Code Block
bgColor#ccccff
#define CUBE(X) ((X) * (X) * (X))
int i = 3;
int a = 81 / CUBE(i);

Non-Compliant

...

Coding Example

In this non-compliant coding example, EOF is defined as -1. The macro replacement list consists of a unary negation operator '-' followed by an integer literal '1'Unexpected behavior resulting from macro expansion is not limited to function-like macros.  The object-like macro definition in this example is non-compliant because its replacement list is not parenthesized.

Code Block
bgColor#FFcccc
#define sum a+bEOF -1
/* ... */
int result = sum*4;

The value of result is a+(b*4) instead of the expected (a+b)*4.

Compliant Solution

if (c EOF) {
   /* ... */
}

Wiki Markup
In this example, the programmer has mistakenly omitted the comparison operator (see \[[MSC02-A. Avoid errors of omission]\]) from the conditional statement, which should be {{c \!= EOF}}. After macro expansion, the conditional expression is incorrectly evaluated as a binary operation: {{c-1}}. This is syntactically correct, even though it is certainly not what the programmer intended.

Parenthesizing the -1 in the declaration of EOF ensures that the macro expansion is evaluated correctly.

Code Block

#define EOF (-1)

Once this modification is made, the non-compliant code example no longer compiles as the macro expansion results in the conditional expression c (-1), which is no longer syntactically valid.

Compliant Solution

The following compliant solution uses parentheses around the macro replacement list and adds the (previously omitted) comparison operatorParenthesizing the macro replacement list yields the expected answer.

Code Block
bgColor#ccccff
#define sumEOF (a+b-1)
/* ... */
intif result(c != sum*4; EOF) {
   /* ... */
}

Note that there must be a space after sum EOF, otherwise it becomes a function-like macro (and one that is incorrectly formed since -1 cannot be a formal parameter).

Exceptions

PRE02-EX1. A macro that expands to a single identifier or function call is not affected by the precedence of any operators in the surrounding expression, so its replacement list need not be parenthesized.

...

Wiki Markup
\[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.10, "Preprocessing directives," and Section 5.1.1, "Translation environment"
\[[Plum 85|AA. C References#Plum 85]\] Rule 1-1
\[[Summit 05|AA. C References#Summit 05]\] Question 10.1