[previous] MISRA-C:2004  Rule  19.4:  (Required) [next] C macros shall only expand to a braced initialiser, a constant, a string literal, a parenthesised expression, a type qualifier, a storage class specifier, or a do-while-zero construct.
These are the only permitted uses of macros. Storage class specifiers and type qualifiers include keywords such as extern, static and const. Any other use of #define could lead to unexpected behaviour when substitution is made, or to very hard-to-read code.

In particular macros shall not be used to define statements or parts of statements except the use of the do-while construct. Nor shall macros redefine the syntax of the language. All brackets of whatever type ( ) { } [ ] in the macro replacement list shall be balanced.

The do-while-zero construct (see example below) is the only permitted mechanism for having complete statements in a macro body. The do-while-zero construct is used to wrap a series of one or more statements and ensure correct behaviour. Note: the semicolon must be omitted from the end of the macro body.

For example:

/* The following are compliant */
#define PI 3.14159F                  /* Constant                      */
#define XSTAL 10000000               /* Constant                      */
#define CLOCK ( XSTAL/16 )           /* Constant expression           */
#define PLUS2( X ) ( ( X ) + 2 )     /* Macro expanding to expression */
#define STOR extern                  /* storage class specifier       */
#define INIT( value ) { ( value ), 0, 0}   /* braced initialiser      */
#define CAT (PI)                     /* parenthesised expression      */ 
#define FILE_A "filename.h"          /* string literal                */
#define READ_TIME_32() \
   do \
   { \
      DISABLE_INTERRUPTS(); \
      time_now = ( uint32_t)TIMER_HI << 16; \
      time_now = time_now | ( uint32_t )TIMER_LO; \
      ENABLE_INTERRUPTS(); \
   } while ( 0 )                     /* example of do-while-zero      */


/* the following are NOT compliant */
#define int32_t long       /* use typedef instead                     */
#define STARTIF if(        /* unbalanced () and language redefinition */
#define CAT PI             /* non-parenthesised expression            */


QAC messages that encompass this guideline:

3409 The replacement list of function-like macro '%s' is not enclosed in ().
3411 Macro defined with unbalanced brackets, parentheses or braces.
3412 Macro defines an unrecognized code-fragment.
3413 Macro definition could be replaced by a typedef.
3431 Macro defines an operator, a punctuator or a control statement keyword.
3452 The replacement list of object-like macro '%s' is not enclosed in ().
3458 Macro defines a braced code statement block.
3460 Macro defines a type specifier keyword.
3461 Macro defines a storage-class specifier/type qualifier sequence.



(c) The Motor Industry Research Association, 2004
QA C Source Code Analyser 8.1.2
MISRA-C:2004 Compliance Module 3.2
© 2013 Programming Research
www.programmingresearch.com
Personality Groups | Glossary | Message Index | MISRA-C:2004 Rule Index Contents