85

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?

3
  • 2
    I simply refer you to Question 5.3 of the C-FAQ. It answers this exact question. Commented Jan 20, 2009 at 3:33
  • 1
    Your code does not use the value if NULL Commented Dec 7, 2011 at 16:11
  • if (NULL) is a direct test of NULL. if (!somePtr) is not. Commented Dec 1, 2021 at 2:03

13 Answers 13

87

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#Null_pointer

Sign up to request clarification or add additional context in comments.

9 Comments

An explicit check may be clearer in some cases, but this is a C idiom that is guaranteed by the language to be valid. :)
i would have cried if all my c code using those if stuffs is now invalid :)
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
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.
NULL is essentially the zero address this is not quite correct. NULL is 0 when converted to a numeric value, but the value of the null pointer may be non-zero Is NULL always zero in C?. The address 0 may be valid, esp. on embedded systems
|
23

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 assignable from and testable against 0.

6 Comments

MMUs were probably more significant than C++ in the change.
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
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...
"giving your if() statement undefined behavior."C FAQ disagrees
0 still remains a perfectly valid address on every arch I have written mmu-code for. It is just a convention of many C runtimes that invalidate its use. In modern linux, as root, you can mmap an object to 0 with MAP_FIXED. In not-long-ago UNIX, it was common to map a read-only zero page to zero so that strcmp(NULL, ...) would not cause a fault, but would only match an empty string.
|
19

It's never safe to assume anything.

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

3 Comments

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: 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: in which language - C or C++? In C99, that's unnecessary, because 'Any two null pointers shall compare equal.'
17

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.

Comments

14
+50

My copy of ISO/IEC 9899:TC3 (Committee Draft — Septermber 7, 2007) says:

6.3 Conversions

1 Several operators convert operand values from one type to another automatically.

6.3.2.3 Pointers

3 An integer constant expression with the value 0 [...] 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.

So far, ptr!=0 is true (1) for every non-null ptr, but it's still open, how two null pointers compare.

6.5.9 Equality operators

5 [...] If one operand is a pointer and the other is a null pointer constant, the null pointer constant is converted to the type of the pointer.

6 Two pointers compare equal if and only if both are null pointers, both are [...]

Hence, ptr==0 is 1 (and ptr!=0 is 0), if and only if ptr is a null pointer.

6.5.3.3 Unary arithmetic operators

5 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 the same holds for !ptr.

6.8.4.1 The if statement

1 The controlling expression of an if statement shall have scalar type.

2 In both forms, the first substatement is executed if the expression compares unequal to 0.

Note, that a scalar type is an arithmetic type or a pointer type (see "6.2.5 Types", clause 21). Putting it together, we have:

  • if (ptr) succeeds ⇔ ptr!=0 is 1 ⇔ ptr is not a null pointer.
  • if (!ptr) succeeds ⇔ ptr==0 is 1 ⇔ ptr is a null pointer.

1 Comment

The cited document is available on open-std.org/jtc1/sc22/wg14/www/standards
7

Yes, if(!p) is valid and guaranteed to work.

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.

https://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p3

This means that (void*)0 is a null pointer. It also means that if p is a pointer, then p==0 is equivalent to p==(void*)0.

It also means that if p is a not a null pointer, then p==(void*)0 will evaluate to 0.

So far, so good.

Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.

http://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p4

Note that "Any two null pointers shall compare equal." This means that if p is a null pointer, then p==0 will evaluate to true, because 0 will be promoted to (void*)0 which is a null pointer. It also mean that no non-null pointer can be equal to a null pointer.

Let's have a look at the negation operator.

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).

http://port70.net/~nsz/c/c11/n1570.html#6.5.3.3p5

This tells us that !p is the same as p==0 by definition, which is the same as p==(void*)0 as mentioned above.

And taking the fact that all null pointers are equal into consideration, this means that p==(void*)0 can only evaluate to true if p is a null pointer and and only false if p is not a null pointer.

So yes, if(!p) is a perfectly safe way to check if p is a null pointer or not.

Comments

4

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 #endif #define NULL 1 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.

3 Comments

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.
Interesting. You can make it not warn by doing: #define NULL (void *) 1
That would be plain wrong. The compiler and the C standard library are bundled together for a reason. If you mess with it, you are breaking this.
3

Yes it:

C standard 6.3.2.3

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.

and 6.3.2.6

Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

-

When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1

Comments

3


What is NULL?

The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant;


What is the value of the null pointer constant?

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.

Example Definition:

#define NULL ((void*)0) 


Evaluating if(NULL)

if ( expression ) statement

if ( expression ) statement else statement

In both forms, the first substatement is executed if the expression compares unequal to 0. In the else form, the second substatement is executed if the expression compares equal §6.8.4.1 Language 133 ISO/IEC 9899:TC3 Committee Draft — Septermber 7, 2007 WG14/N1256 to 0. If the first substatement is reached via a label, the second substatement is not executed.


So yes if the compiler is compliant with ISO C99 you can assume that the statement below will always execute.

if (!NULL) { statement; } 


Above quotations are from ISO/IEC 9899:1999 (C99). You can read it here.

Comments

0

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.

2 Comments

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.
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.
0

According to me, it's not always safe to assume that. Since, depending on which headers have been included in a program, it can have been redefined. But according to the standard, the null pointer constant is guaranteed not to point to any real object and has a type void *.

In our case, the declaration void *somePtr = NULL could also be void *somePtr = 0 with 0 as null pointer.

“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.” https://www.geeksforgeeks.org/few-bytes-on-null-pointer-in-c/

That simply means, evaluating *somePtr at that specific point could result to false.

Another reference can be https://www.gnu.org/software/libc/manual/pdf/libc.pdf at page 944 A.3 about NULL Pointer Constant

Comments

-2

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.

1 Comment

@Matt: Don't you mean a macro :-)?
-6

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

3 Comments

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.
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.
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?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.