5

Can someone explain how while(foo) vs while(foo != NULL) are equivalent? Also:

while(!foo) vs while(foo == NULL)

I know that ! is not, but that is about all I know.

MortalMan
  • 2,582
  • 3
  • 23
  • 47
  • 1
    If `foo` is a pointer, then the definition of `while(foo)` is `while(foo != NULL)`. Therefore they are equivalent. – M.M Mar 30 '15 at 02:28
  • 1
    Possible duplicate of [Can I use if (pointer) instead of if (pointer != NULL)?](https://stackoverflow.com/questions/17772103/can-i-use-if-pointer-instead-of-if-pointer-null) – Daniel McIntosh Sep 13 '19 at 02:14

5 Answers5

7

Assuming foo is of pointer type, while (foo) and while (foo != NULL) are exactly equivalent. Both are also equivalent to while (foo != 0). (In my opinion while (foo != NULL) more clearly expresses the intent.)

In any context requiring a condition (if(), while(), a few others), the expression is treated as true if the condition compares unequal to zero, false if it compares equal to zero.

NULL is a macro that expands to an implementation-defined null pointer constant. Comparing a pointer value to NULL yields a true value for a null pointer, a false value for any non-null pointer.

The constant 0 is a null pointer constant [*]. (This doesn't mean that a null pointer has the same bit representation of 0x00000000 or something similar, though it often does; it means that a constant 0 in source code can denote a null pointer.) As you'd expect, comparing a pointer value to a null pointer constant tells you whether that pointer is a null pointer or not. In while (foo), the comparison to zero is implicit -- but it still tests whether foo is a null pointer or not.

More generally, while (foo) compares foo to 0, which is equivalent to comparing it to "zero" of the appropriate type. while (foo) is always equivalent to while (foo != 0). For a floating-point value, it's also equivalent to while (foo != 0.0). For a character value, it's equivalent to while (foo != '\0'). And, as we've seen, for a pointer value, it's equivalent to while (foo != NULL).

(In C, a comparison operator always yields an int value of 0 if the condition is false, 1 if it's true -- but any non-zero value is treated as true, via the implicit inequality comparison to zero.)

[*] A null pointer constant is defined as an integer constant expression with the value 0, or such an expression cast to void*. A null pointer constant isn't necessarily of pointer type, but converting it to pointer type yields a null pointer value. Comparing a pointer value to 0 causes the 0 to be implicitly converted to the pointer type so the comparison can be done.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 1
    @chux: Updated. (`0` is both an expression of type `int` and a null pointer constant; I can see that might cause confusion.) – Keith Thompson Mar 30 '15 at 16:03
  • Yes it did for me and I enjoying a lunch of [crow](http://en.wikipedia.org/wiki/Eating_crow). It turns out `#define NULL 0` can be valid as so can `#define NULL ((void*)0)`. The latter has advantages, but both are compliant. – chux - Reinstate Monica Mar 30 '15 at 16:07
  • @chux: There's an obscure argument that `#define NULL ((void*)0)` is not valid. (N1570 6.5.1p5 doesn't say that a parenthesized null pointer constant is a null pointer constant.) But in practice it's certainly intended to be valid. – Keith Thompson Mar 30 '15 at 16:21
2
while(foo);

and

while(foo != NULL)

Are equivalent simply because NULL is a macro that expands to either 0, or (void*)0 or 0L, given that in C 0 evaluates to false(and any non-zero number to true) then

while(foo); //while foo isn't 0
while(foo != NULL) //expands to while(foo != 0) < while foo isn't 0
Alex Díaz
  • 2,303
  • 15
  • 24
  • Depends on type of `foo`. Consider `double foo`. `while(foo);` is OK, yet `while(foo != NULL)` does not compile: "invalid operands to binary `!=`" depending on how `NULL` is defined which should be a null pointer constant and not `0` as suggested here. – chux - Reinstate Monica Mar 30 '15 at 03:49
  • @chux Sure, this is assuming `foo` is either a pointer or an `int` however `NULL` is guaranteed to compare equal to 0, in practice I think most implementations do use 0 as `NULL`. – Alex Díaz Mar 30 '15 at 04:01
  • "most implementations do use 0 as NULL" Disagree, My gcc 4.9.2 uses `#define NULL ((void *)0)`. MS Visual 2010, when compiling as `C` uses `#define NULL ((void *)0)`. Perhaps you are thinking of how `NULL` is defined in another language like `C++`. – chux - Reinstate Monica Mar 30 '15 at 15:04
  • @chux I said that in my answer "NULL is a macro that expands to either 0, or (void*)0 or 0L" – Alex Díaz Mar 30 '15 at 15:06
  • I assert `NULL` can be `(void*)0`, but not `0`, nor `0L`. Your answer states it could be `0, or (void*)0 or 0L`. You comment "most implementations do use 0 as `NULL`", is not backed by any example versus 2 counter examples given. – chux - Reinstate Monica Mar 30 '15 at 15:19
  • @chux what I meant by "do use 0 as. NULL" is "do use some form of 0, either (void*)0, 0 or 0L as NULL", read http://c-faq.com/null/long0.html, as for "most implementations use 0 as NULL", I never tried to pass that as a hard fact – Alex Díaz Mar 30 '15 at 15:30
  • Per chat with a3f concluded `NULL` may be either `0` or `(void *)0` - I stand corrected. – chux - Reinstate Monica Mar 30 '15 at 16:02
1

while (expression) repeats the enclosing block as long as expression evaluates to any non-zero value. When expression evalutes to 0, the while loop ends.

An expression that's a pointer type is considered to be non-0 if the pointer value is not std::nullptr, or NULL.

The ! operator is a boolean not operator.

Therefore

 while (foo)

And

 while (foo != NULL)

are logically equivalent to each other. Therefore, the logical inverse of the two are also equivalent to each other.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
1

NULL is a symbolic constant, you can think of it as a sort of replacement text. NULL is just something that the compiler later replaces with a zero, so writing while (foo != NULL) is the same as writing while (foo != 0). Remember, == says yes if what's to the left of it is equal to what's to the right of it, whereas != says yes if what's to the left of it is NOT equal to what's to the right of it.

In C, the number 0 always means false and every other number means true. So while (foo != 0) is the same as saying "Run the code in this loop while foo is true". while (1), for example, is the same as saying "Run the code in this loop forever", because 1 is a number that is always different from zero and hence is always true.

In C, if you use just foo where a true-or-false kind of value is expected, it's the same as saying foo != 0, that's kind of like a shortcut you can use, it's the same as asking "is foo true?". ! means "not", so asking !foo is the same as asking "is foo NOT true?", in other words "is foo false?". This means that while (!foo) is the same as "Run the code in this loop while foo is false", which is the same as while (foo == 0) since zero means false, which is the same as while (foo == NULL) since NULL means zero.

Think of it like this: the code in a loop will only run if what's in the parenthesis is true (that is, non-zero). So in while (foo) the computer will ask "is foo non-zero?", if yes the loop keeps going. Now, if you have while (!foo), the computer will ask "is foo NOT non-zero?", if yes the loop keeps going. The loop only stops when the expression in the parenthesis results in false.

NULL is defined in several standard header files, it's not a keyword like if and while, you need to include a header file that defines it to be able to use it. The idea is that when a pointer points to address zero, it's called a "null pointer", that's why it's called NULL, it's used when you want to say "zero the address" rather than merely "zero the number".

Edit: As correctly pointed out by Matt McNabb, NULL may be defined as 0 or as (void *)0. To stay clear of any doubt, I quote the C11 standard:

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

And later on

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

Then, in Section 7.19:

3 The macros are

NULL

which expands to an implementation-defined null pointer constant; and

offsetof(type, member-designator)

which expands to...

And the text goes on. So (void *)0 and 0 are valid implementation-defined null pointer constants.

danieltm64
  • 471
  • 2
  • 4
  • `NULL` may be either `0` or `(void *)0`. – M.M Mar 30 '15 at 03:25
  • @Matt McNabb Can `NULL` be `0`? As I read C spec, `NULL` is a "null pointer constant". `0` is an `int`. Maybe same value, but differing types and sizes. – chux - Reinstate Monica Mar 30 '15 at 03:53
  • @chux it then goes on and defines `null pointer constan`t on being an integer constant that equals zero or the same cast to `void*`. – a3f Mar 30 '15 at 10:10
  • @a3f My ref for "NULL which expands to an implementation-defined null pointer constant" is form C11 §7.19 3. Where is the "...on being an integer constant that equals zero ..."? – chux - Reinstate Monica Mar 30 '15 at 14:16
  • @chux C11 n1570: §6.3.2.3p3. Of course the implementation is free to choose a value apart from all bits zero to represent `NULL`, it's required though to treat the integer `0` as `NULL` when in a "pointer context". – a3f Mar 30 '15 at 14:19
  • @a3f Agree about "treat the integer `0` as `NULL`" in a "pointer context", but that does not mean "defines `null pointer constant` (`NULL`) being an integer constant" in your earlier comment. To be clear, `NULL` not only has a value, but a type. As I read the C spec, that type is some pointer and `0` is not a pointer. – chux - Reinstate Monica Mar 30 '15 at 15:12
  • `"An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant"` == `"defines null pointer constant on being an integer constant that equals zero or the same cast to void*"`, at least to me. – a3f Mar 30 '15 at 15:15
  • 1
    Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/74114/discussion-between-chux-and-a3f). – chux - Reinstate Monica Mar 30 '15 at 15:27
  • 1
    @danieltm64 Concluded with a3f that Matt McNabb is correct with `NULL` may be either `0` or `(void *)0`. – chux - Reinstate Monica Mar 30 '15 at 16:00
0

a while loop can run like so:

while(1) //This will run forever.

while(true) //This will run forever.

NULL is like 0, so if you have while(foo != NULL), this is saying that while(foo is not equal to 0, so while it is equal to 1 or something else) run it.

Tman
  • 136
  • 8