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
  • 7,096
  • 19
  • 80
  • 107
  • 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
  • 51,233
  • 8
  • 91
  • 143
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
  • 272,464
  • 47
  • 358
  • 399
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,286
  • 1
  • 22
  • 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
  • 22,195
  • 6
  • 45
  • 72
0

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

Paul Mitchell
  • 3,241
  • 1
  • 19
  • 22
0

To enforce the ; , use

#define NULLCHECK(x) do { assert((X)); } while (0)
MSalters
  • 173,980
  • 10
  • 155
  • 350