7

When testing for NULL, I see a lot of code that uses !var. Is there a reason to use this kind of test as opposed to the more explicit var == NULL. Likewise would if (var) be a correct test for an item being non-null?

Matt
  • 7,100
  • 3
  • 28
  • 58
  • For formal reasons, I prefer the latter -- it makes the intent clearer. But either is acceptable. – Hot Licks Sep 30 '12 at 19:47
  • Found a very similar question: http://stackoverflow.com/questions/459743/is-null-always-false – Matt Sep 30 '12 at 19:48
  • possible duplicate of [C/C++ Checking for NULL pointer](http://stackoverflow.com/questions/3825668/c-c-checking-for-null-pointer) – Jens Gustedt Sep 30 '12 at 20:12
  • Both are valid, and mean the same thing if `var` is a pointer object. Personally, I strongly prefer `var == NULL` because it's more explicit. Many C programmers tend to value terseness over explicitness. – Keith Thompson Sep 30 '12 at 20:19

4 Answers4

11

The difference between:

!var

and

var == NULL

is in the second case the compiler have to issue a diagnostic if var is not of a pointer type and NULL is defined with a cast (like (void *) 0).

Also (as pointed by @bitmask in the comments) to use the NULL macro, you need to include a standard header that defines the NULL macro. In C the NULL macro is defined in several headers for convenience (like stddef.h, stdio.h, stdlib.h, string.h, etc.).

Otherwise the two expressions are equivalent and it is just a matter of taste. Use the one you feel more confortable at.

And for your second question if (var) is the same as if (var != NULL) with the difference noted above.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • 2
    Note that you require at least one of several headers for `NULL` to be defined. – bitmask Sep 30 '12 at 19:41
  • http://c-faq.com/null/ptrtest.html says `if(var) is equivalent to if(var != 0)` and a lot more stuff about null pointers. Also isn't this question already asked? see http://stackoverflow.com/a/3825704/1273830 is it different somehome? – Prasanth Sep 30 '12 at 19:52
  • But it makes *no* difference if `NULL` is defined as just `0`, which is perfectly legal. (I don't think C++ allows such a definition, but C does.) – Keith Thompson Sep 30 '12 at 20:17
  • @KeithThompson Actually, in C++ NULL is guaranteed to be 0. C and C++ are different in this case. In C, NULL can be a pointer (void*)0, and in theory it could also be something completely different, as long as it translated into a null pointer constant. – Lundin Sep 30 '12 at 20:53
  • @Lundin: I actually knew that; I just got it backwards when I wrote it. Both C and C++ require `NULL` to expand to an implementation-defined *null pointer constant*, but they define "null pointer constant" differently. In C, a null pointer constant is "An integer constant expression with the value 0, or such an expression cast to type void *". In C++, it's "an integral constant expression prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t"; I think `nullptr_t` is a recent addition to the language. `#define NULL 0` is valid in both languages. – Keith Thompson Sep 30 '12 at 21:35
3

The var == NULL version has one major advantage: it makes it possible for the compiler and static analysers to find one particular common bug.

Suppose "var" is not a pointer, but an allocated variable. if(!var) would then be a bug passing by undetected.

NULL is often declared as #define NULL ((void*)0). This declaration isn't mandatory by the standard, but one of the most common ones. A compiler with half-decent type checking would then be able to yield a warning for code like this:

int var = ...;
if(var == NULL)  // compiler warning, var is not a pointer

Apart from the above advantage, it is also stylistically correct not to use the ! operator, since it is a logical operator, meant to be used on boolean variables, not pointers. It just works since C has no strong typing.

I would recommend to follow MISRA-C in this matter, which dictates that checks against NULL or zero should be made explicit. if(x != NULL) rather than if(x). The rationale for those rules is more readable code. It translates to the very same machine code anyhow, so there is no harm in making your code easier to read.

Lundin
  • 195,001
  • 40
  • 254
  • 396
2

The ISO/IEC 9899 standard states that:

  1. as of the language: an integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

  2. as of the libraries: NULL is a macro that expands to the implementation-defined null pointer constant.

That means the expressions you give are equally "correct". The reason to prefer one form over another is largely a matter of taste.

geocar
  • 9,085
  • 1
  • 29
  • 37
  • That is, if you have a minimal compiler with no warnings beyond what is required by the standard. If you have a modern one, lets say one made after 1991, you'd get compiler warnings if you tried to compare a non-pointer variable against NULL. – Lundin Sep 30 '12 at 20:51
2

From the C standard:

Arithmetic types and pointer types are collectively called scalar types.

The operand of the unary + or - operator shall have arithmetic type; of the ~ operator, integer type; of the ! operator, scalar type.

The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E).

So, that should answer your question.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180