Coding best practices: Minimizing the use of macros

November 30th, 2007

This coding ‘best practice’ is the first in the series of many posts that I will be making. Many of them have been introduced to me only recently, so it’s unlikely you will see this in my old code. I am making these posts as I think they are essential to every C++ programmer.

Lets get started on the first one…
Some may call this an opinion, but I call this a good programming practice.
Don’t declare a macro unless you cannot do without them. Below I have presented some problems plaguing macros and some workarounds.

1. Macros modify the code before the compiler sees it. This makes it harder for you to debug your program, step into code and find bugs.

2. Macros don't obey scoping rules. So the following example

// The macro below could very well be in another header file
// that you never seen or totally forgot about
#define width 20

// And then you name a variable the same name,
// forgetting there was a macro with the same name
// It’s than you think to forget, especially if the macro is
// hidden in one of those header files
void RenderRect(int height, int width) // …

Workarounds
Below are some workarounds for some common uses you might have for macros

// 1 //// Global strings
// macro:
#define SZ_HELLO "Hello world"
// workaround:
char const szHello[] = "Hello world";

// 2 //// Global setting
// macro:
#define NMAX 5
// workaround:
const int nMax = 5;

// 3 //// Generic functions
// macro:
#define SQUARE( x ) ((x)*(x))
// workaround:
template<typename T>
T inline square(T &x)
{
  return x * x ;
}

End note

Of course there are some places where only a macro can get the job done. In these cases go ahead and use a macro, but follow a strict naming convention for your macros so you will not confuse them with a standard variable later on.

Leave a Reply