HOWTO write a macro
From ODE Wiki
Please read following instructions regarding writing macros. If you obey these rules you will never have bugs like one fixed by commit #1326.
WARNING
Don't forget also that macros should be avoided wherever possible. If there's are good reason to use one (and there aren't that many), then it should be associated with a comment saying exactly why. In most cases macros could be replaced with inline functions or templates.
- All functional macros parameters MUST be enclosed in parentheses if used in ANY expression inside of macro implementation.
- If functional macro parameter is passed unchanged to a function or another macro it DOES NOT NEED to be enclosed in parentheses because it will be enclosed inside of macro being called. Similarly, expressions passed to macro parameters do not need to be enclosed in parentheses.
- A macro SHOULD NOT have last semicolon in its definition as a semicolon will be placed after macro instantiation in code.
- Every macro MUST be an atomic expression with regard to any operators. If a macro is an expression its definition MUST be enclosed in parentheses.
The aim of these rules is to make all the macros to behave like functions and all macro parameters to behave like function parameters.
IT DOES NOT MATTER IF YOU ARE PASSING EXPRESSIONS AS PARAMETERS NOW AND IF YOU ARE OR ARE NOT GOING TO DO IT IN THE FUTURE. SOMEBODY ELSE CAN START DOING IT WITH YOUR MACROS BECAUSE IT IS A COMMON APPROACH TO EXPECT MACRO BEHAVIOR TO MATCH FUNCTION BEHAVIOR.
Some examples follow:
INCORRECT
//! Inserts an element at the last position
#define GIM_DYNARRAY_PUSH_ITEM(type,array_data,item)\
{\
if(array_data.m_reserve_size<=array_data.m_size)\
{\
GIM_DYNARRAY_RESERVE_SIZE(type,array_data,(array_data.m_size+G_ARRAY_GROW_SIZE));\
}\
type * _pt = GIM_DYNARRAY_POINTER(type,array_data);\
memcpy(&_pt[array_data.m_size],&item,sizeof(type));\
array_data.m_size++; \
}\
CORRECT
//! Inserts an element at the last position
#define GIM_DYNARRAY_PUSH_ITEM(type,array_data,item)\
{\
if((array_data).m_reserve_size<=(array_data).m_size)\
{\
GIM_DYNARRAY_RESERVE_SIZE(type,array_data,(array_data).m_size+G_ARRAY_GROW_SIZE);\
}\
type * _pt = GIM_DYNARRAY_POINTER(type,array_data);\
memcpy(&_pt[(array_data).m_size],&(item),sizeof(type));\
(array_data).m_size++;\
}\
INCORRECT
///Swap numbers
#define SWAP_NUMBERS(a,b){ \
a = a+b; \
b = a-b; \
a = a-b; \
}\
CORRECT
///Swap numbers
#define SWAP_NUMBERS(a,b){ \
(a) = (a)+(b); \
(b) = (a)-(b); \
(a) = (a)-(b); \
}\

