3
#ifndef MACROS_NULLCHECK_H_
#define MACROS_NULLCHECK_H_

#include <assert.h>

#define NULLCHECK(x) assert(x != (void *) 0);

#endif

If I used the above style as a template for declaring Macros, what provisos would you have?

Ande Turner
  • 6,838
  • 19
  • 78
  • 106
  • 1
    disregarding your question for a moment: the macro `NULLCHECK()` is useless: pointers are scalar types and therefore can be used in boolean contexts; `NULLCHECK(foo)` does exactly the same thing as `assert(foo)` – Christoph Sep 10 '09 at 10:57
  • @Christoph True, see http://stackoverflow.com/questions/1296843/what-is-the-difference-between-null-0-and-0/1296865 for more. – Andrew Keeton Sep 10 '09 at 10:59
  • 1
    @Christoph: I disagree: Assertions should be Overt. If the assertion is actually invoked then a more overt message will be displayed. ie: `"Assertion violation: file exe.c, line $: (foo) != (void *) 0"` vs. `"Assertion violation: file exe.c, line $: (foo)"` – Ande Turner Sep 10 '09 at 14:23

6 Answers6

14
  • put parenthesis around the argument (it prevents problems when passing expressions)

  • don't put ; at the end (the use will be more natural)

    #define NULLCHECK(x) assert((x) != (void*)0)

AProgrammer
  • 49,582
  • 8
  • 87
  • 140
3

One change I might make would be to comment the closing #endif:

#endif  // MACROS_NULLCHECK_H_

It makes it easier to understand what that #endif is doing there when the file gets longer than a screen.

RichieHindle
  • 258,929
  • 46
  • 350
  • 392
3

Generally speaking, you should always put macro arguments in brackets in the expansion, i.e. in your case

assert((x) != (void*) 0)

This is because if you don't then any expressions (rather than simple variables) which you pass in may mess up the variable expansion.

I would also suggest that you DON'T put the semicolon at the end of the macro definition, so that you have to call it like

NULLCHECK(pSomething);

which just looks more C-like & consistent with the rest of your code.

AAT
  • 3,137
  • 1
  • 20
  • 26
1

Some good macro practices from the CERT C Secure Coding Wiki:

PRE00-C. Prefer inline or static functions to function-like macros
PRE01-C. Use parentheses within macros around parameter names
PRE02-C. Macro replacement lists should be parenthesized
PRE03-C. Prefer typedefs to defines for encoding types
PRE10-C. Wrap multi-statement macros in a do-while loop
PRE11-C. Do not conclude a single statement macro definition with a semicolon
PRE31-C. Never invoke an unsafe macro with arguments containing assignment, increment, decrement, volatile access, or function call
PRE32-C. Do not use preprocessor directives inside macro arguments

Andrew Keeton
  • 20,707
  • 6
  • 44
  • 71
0

Looks good. It's a pattern I use a lot.

Paul Mitchell
  • 3,181
  • 18
  • 22
0

To enforce the ; , use

#define NULLCHECK(x) do { assert((X)); } while (0)
MSalters
  • 167,472
  • 9
  • 150
  • 334