tags:

views:

1144

answers:

9

Is it safe to assume that NULL always translates to false in C?

void *somePtr = NULL;

if (!somePtr) {
  /* This will always be executed? */
}

Or should an explicit check against the value of NULL be made?

+5  A: 

It's never safe to assume anything.

An explicit check is also more clear about what you're testing.

akatakritos
+1 Explicit is always better than implicit.
Andrew Hare
We used to take it one step further and define a type-specific nil value for each of our typedef'ed items: structs, int, longs, whatever. That way the conditional would read "if (foo != fooNil) { etc. }". Disclaimer: I used to work for Simonyi at Xerox so my brain was contaminated.
Peter Rowell
@Peter Rowell: for quite a long time, I used #define NIL(x) ((x)0) to achieve roughly that effect: NIL(foo), NIL(char *), NIL(bar), etc.
Jonathan Leffler
@Jonathan: in which language - C or C++? In C99, that's unnecessary, because 'Any two null pointers shall compare equal.'
Christoph
+2  A: 

NULL is defined as a constant pointer that is guaranteed to point to a useless/non-existent place in memory. Most implementations of NULL are ((void *)0) but it is not mandatory that this is so.

dreamlax
In C, that's correct. Be aware that in C++, it is most frequently just 0, mainly because you can't convert a void pointer to any other type without an explicit cast.
Jonathan Leffler
In any correct C compiler "NULL == 0" is true, even if a null pointer does not really contain 0.What you can't do is memzero a pointer and then assume it will be NULL.
Captain Segfault
@Captain Segfault: Exactly. I don't understand why people are having trouble with this.
Anthony Cuozzo
A: 

*NULL always targets to 0x00L. you can consider that false, but to be sure always do a explicit check.

Gabriel Sosa
NULL is implementation specific. In some cases, such as embedded machines, you may want to access the very first byte in RAM which would be addressed as 0. NULL is defined by the standard as a pointer that is guaranteed not to point to any usable point in RAM.
dreamlax
Dereferencing either NULL itself or a null pointer invokes undefined behaviour -- or, on big enough machines with MMUs, a core dump or equivalent. The "all the world's a VAX" syndrome died a while ago - there, derefencing NULL did yield a zero byte.
Jonathan Leffler
The lower 128 bytes of a vax machine give an access violation when you dereference them. Do you have a program that demonstrates the symptoms you observed?
EvilTeach
+22  A: 

Yes. NULL evaluates to false, since C considers any non-zero value true and any zero value false. NULL is essentially the zero address and is treated as such in comparisons, and I believe would be promoted to an int for the boolean check. I would expect that your code is readable to anyone familiar with C although I would probably make the check explicit.

In C and C++ programming, two null pointers are guaranteed to compare equal; ANSI C guarantees that any null pointer will be equal to 0 in a comparison with an integer type; furthermore the macro NULL is defined as a null pointer constant, that is value 0 (either as an integer type or converted to a pointer to void), so a null pointer will compare equal to NULL.

Ref: http://en.wikipedia.org/wiki/Null_pointer#The_null_pointer

tvanfosson
An explicit check may be clearer in some cases, but this is a C idiom that is guaranteed by the language to be valid. :)
Greg D
i would have cried if all my c code using those if stuffs is now invalid :)
Johannes Schaub - litb
The standard isn't very clear on the issue: it's guaranteed that 0 cast to a pointer type will be a null pointer, but afaik it does not specify what will happen when a null pointer is cast to int!
Christoph
you don't cast to int though. you compare 0 to the pointer. 0 is a null pointer constant. and if you compare a null pointer constant to a pointer, the null pointer constant will become a null pointer of the right type. and a null pointer compares unequal to every valid pointer. that's what he wants
Johannes Schaub - litb
The situation in the standard is more convoluted: it allows null pointer to have address eg. 0xdeadbeef, but IMHO still evaluate to false. That's because there is no conversion in the if-clause, the condition should have scalar type (pointer is a scalar type) and NULL pointer compares equal to 0
jpalecek
yes jpalecek that's the whole point. a "null pointer" does not mean "zero bits". a null pointer is a black-box. In the if, the " != 0" is implicit, and in !ptr, the "== 0" is implicit. so if you do if(ptr), it will compare the pointer to a null pointer constant.
Johannes Schaub - litb
Perhaps tvanfosson could scratch the part about the promotion to an integer for the boolean check?
Christoph
+3  A: 

The 'C' language dates from an era where (void*)0 could actually be a valid pointer. It is not that long ago, the 8080 and Z80 microprocessors had an interrupt vector at address 0. Faced with such architecture choices, it couldn't do anything but let a header file declare the value of NULL. There were some compilers out there, now long forgotten, where NULL was not equal to (void*)0 (0xffff was the next alternative), thus giving your if() statement undefined behavior.

C++ mercifully put an end to this, a null pointer is guaranteed to be 0.

Hans Passant
MMUs were probably more significant than C++ in the change.
Jonathan Leffler
About your C++ sentence: that's wrong. 0 is not a null pointer. 0 is a null pointer constant. void *p = 0; now, p is a null pointer. it's a difference, because a null pointer has pointer type, where a null pointer constant has integer type and is a constant expression
Johannes Schaub - litb
C99 guarantees that 0 cast to a pointer type will be a null pointer as well - I never bothered to read previous standards, so no idea when this happened...
Christoph
A: 

Yes, mostly.

First off, NULL is a typedef. I could royally screw you over by saying in a previously included header

#define NULL 1

This might not make a lot of sense, but since when has other people's code ever made sense? :)

Also, while it's probably syntactically safe, it's not semantically correct. NULL means "nothing", neither true or false or a boolean value or int or string. It means "a symbol for nothing". So testing for NULL is more like a philisophical issue: If a tree falls in the forest, and if(listener), does it make a sound?

Do everyone a favor and be clear about testing against NULL.

Matt
@Matt: Don't you mean a macro :-)?
Anthony Cuozzo
+5  A: 

Yes (at least for any standards compliant C compiler!)

From the comp.lang.c FAQ:

Q: Is the abbreviated pointer comparison ``if(p)'' to test for non-null pointers valid? What if the internal representation for null pointers is nonzero?

A: It is always valid.

Captain Segfault
+1  A: 

I simply refer you to Question 5.3 of the C-FAQ. It answers this exact question.

Anthony Cuozzo
A: 

NULL is just a preprocessor definition. It's in stdio.h. Typically, only an insane person would redefine it, but it's possible. An example:

#include <stdio.h>
#ifdef NULL
#undef NULL
#define NULL 1
#endif

void main()
{

        if (NULL)
                printf("NULL is true\n");
        else
                printf("NULL is false\n");
}

This code will print "NULL is true". Try it if you don't believe me. Your compiler might not even warn you that you're doing something weird.

Brendan Dowling
But if you define NULL to 1 and assign somePtr = NULL, you'll at least get a warning that you're converting an integer to a pointer.
Mark James
Interesting. You can make it not warn by doing: #define NULL (void *) 1
Brendan Dowling