Fri, 13 Mar 2009

Valid Uses of Macros

So, C has a preprocessor, and it can be used for evil: particularly function-style macros (#define func(arg)) are generally considered suspect. Old-timers used to insist all macros were SHOUTED, but it can make innocent (but macro-heavy) code damn ugly.

Remember, it's only a problem when it's Easy to Misuse, and if you've written something that's easy to misuse, maybe a rethink is better than an ALL CAPS warning.

There is one genuine and unescapable use for macros:

Macros which deal with types, or take any type
The classic here is
#define new(type) ((type *)malloc(sizeof(type)))
But consider also the Linux kernel's min() implementation:
 #define min(x,y) ({ \
	typeof(x) _x = (x);	\
	typeof(y) _y = (y);	\
	(void) (&_x == &_y);		\
	_x < _y ? _x : _y; })
which uses two GCC extensions to produce a warning if x and y are not exactly the same type.

And there are several justifiable but more arguable cases:

Const-correct wrappers
If you need to wrap a struct member access, it's annoying to do it as an inline function. To be general a function needs to take a const pointer argument, then cast away the const (see strchr). Const exists for a reason, and stealing it from your callers is a bad idea. A macro
#define tsk_foo(tsk) ((tsk)->foo)
maintains const correctness, at the slight cost of type safety (you could hand anything with a foo member there, though it's unlikely to cause problems and can be fixed with a more complex macro.
Debugging macros
Generally just add __FILE__ and __LINE__ to a function call. The non-debug versions are generally real functions.
Genuinely fancy tricks
There's no good way around a macro for things like ARRAY_SIZE and BUILD_BUG_ON (these taken from CCAN):
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + _array_size_chk(arr))
#define BUILD_ASSERT(cond) do { (void) sizeof(char [1 - 2*!(cond)]); } while(0)

More questionable still:

Macros which declare things
This is for things which need initialization, eg. LIST_HEAD in the kernel (or ccan/list) expects an "empty" list to be pointing to itself. While this is convenient, nothing else in C self-initializes so it's arguably better to provide an "EMPTY_LIST(name)" macro. You get a nice crash if you forget (except on stack vars).

Macros which iterate
list_for_each() (ccan/list.h version of the kernel's list_for_each_entry):
#define list_for_each(h, i, member)					\
	for (i = container_of_var(debug_list(h)->, i, member);	\
	     &i->member != &(h)->n;					\
	     i = container_of_var(i->, i, member))
It's less explicit, but much shorter than having three macros and using them to loop:
for (i = list_start(&list, member); i != list_end(&list, member); i = list_next(&list, member, i))
If we sacrifice a little efficiency for convenience, we can make list_start() and list_next() evaluate to NULL at the end of the list, and I prefer it over the list_for_each() macro:
 for (i = list_start(&list, member); i; i = list_next(&list, member, i))
Of course, it wouldn't be a complete post on macros without mentioning things you should never do:
Modify your arguments.
C coders don't expect magic changes to parameters. From kernel.h:
#define swap(a, b) \
	do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
Embed control statements to places outside the macro.
Putting 'return' in macros is only ok if the macro is called, say, COMPLAIN_AND_RETURN. And then it's probably still a bad idea.

The classics: use too few brackets, or allow multi-evaluation.
The former is unforgivable; it cost be 1/2 a day of my life once when I was younger and using another coder's RAD2DEG() macro. The latter can be avoided with gcc extensions (see min() above), or sometimes using sizeof().

[/tech] permanent link