7

When I wish to check if a value is 0 in C, how is it idiomatically done?

  • if (!num)
  • if (num == 0)
Paul Manta
  • 30,618
  • 31
  • 128
  • 208

8 Answers8

15

While this is a matter of taste, I find it pretty much depends on intention. If the value is to be used as a boolean, ! is alright. If the value is counting something the equality makes more sense.

if (!isVisible) {...}
if (isVisible == 0) {...} // Intention not as clear as line above.

if (numberOfItems == 0) {...}
if (!numberOfItems) {...} // Intention not as clear as line above.
DarkDust
  • 90,870
  • 19
  • 190
  • 224
6

I always prefer the second way:

if (num == 0)

As num == 0 or ptr == NULL evaluates to a boolean which is the intent. The Java compiler enforces this form, but C/C++ compilers don't.

The worst example of this would be:

if (!strcmp(str, "something"))

Which really disguises its intent as the strcmp family of functions don't return boolean, they return positive, zero, or negative (as pointed out by @JoachimPileborg).

However if the int is being used to represent a boolean type, which C does not have a builtin type for, then this form is OK:

if (!b)

But this can be made self documenting by creating a custom type:

typedef int bool;
#define true 1
#define false 0

bool b = true;
if (!b)
{
   ... etc
}
unwind
  • 391,730
  • 64
  • 469
  • 606
trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • `strcmp` is a good example. I like that in Objective-C, Apple has provided an enum with `NSOrderedAscending`, `NSOrderedSame` and `NSOrderedDescending` which makes the intention more clear than -1, 0 and 1. – DarkDust Oct 26 '11 at 09:42
  • 2
    Regarding the `strcmp` case, the return value can actually be any positive or negative value, besides zero. Never compare against `1` or `-1`. – Some programmer dude Oct 26 '11 at 09:42
  • @JoachimPileborg: Agreed; you'd use `< 0` , `== 0` or `> 0`. – trojanfoe Oct 26 '11 at 09:43
  • Oh yuck! No! "As num == 0 or ptr == NULL evaluates to a boolean which is the intent. The Java compiler enforces this form, but C/C++ compilers don't." This question is tagged C. In C these operations do not evaluate to a boolean. They evaluate to 0 or 1, explicitly in the specification an __int__ 0 or 1. – James Greenhalgh Oct 26 '11 at 10:13
  • @JamesGreenhalgh: So you prefer something like: `char *p = &something; if (p) { ... }` ? – trojanfoe Oct 26 '11 at 10:29
  • @trojanfoe I'm not expressing any preference for idioms. I'm expressing a preference for accurate statements about the result of expressions. Equality and Comparison operators return an __int__ of value 0 or 1. This distinction is important in C99, where evaluation to boolean would imply a result of type _Bool. – James Greenhalgh Oct 26 '11 at 11:02
  • @JamesGreenhalgh: Interesting; I'd never even heard of `_Bool` let alone used it. You live and learn :) – trojanfoe Oct 26 '11 at 11:13
3

Whatever the others told you WITH AN EXCEPTION!

Don't do it with float and double. IEEE 754 floats/doubles/long doubles (the most commonly used) often don't contain exact values, so comparing them directly with 0 is foolish (or doing if (!floatValue))

Example: http://ideone.com/PIUflA

float f = 0.3;
f -= 0.2;
f -= 0.1;

if (!f)
{
    printf("zero\n");
}
else
{
    printf("non zero\n");
}

if (f == 0)
{
    printf("zero\n");
}
else
{
    printf("non zero\n");
}

With unoptimized compilation can return (on ideone does)

non zero
non zero

(if you enable optimizations, the compiler could pre-compute some values in higher precision and round them to 0)

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • But doesn't that have more to do with `0.1` not being representable in base 2? – Paul Manta Oct 26 '11 at 09:49
  • 1
    @Paul Yes (and even `0.2` and `0.3`). But the "why" isn't really relevant. The important thing was `"Don't do it with float an double"` – xanatos Oct 26 '11 at 09:52
  • The reason given is wrong. "often don't contain exact values" is not true: floating-point types contain exact values - but the result of a computation might not be what a person naively assumes. If you assign a literal "0" to a float then it always will compare true to "0". and that is the same for -0 too as that compares as equal to +0. – ABaumstumpf Dec 17 '20 at 11:43
2

I think it depends on the context. If the variable refers to a boolean value is better first choice. Otherwise, the second is better.

vicentazo
  • 1,739
  • 15
  • 19
1

It's done however you want it to be done, in terms of your style. I don't see it as mattering as long as your consistent and it's clear on what you're trying to do, or if you do it in cases where it may flow better in an English sentence and may put emphasis on what your doing.

For sake of clarity I usually have if (num == 0), since it takes less thinking to understand what I'm doing when I'm going over my code.

AusCBloke
  • 18,014
  • 6
  • 40
  • 44
0

!!value will work too if you want to check if value is non-zero.

!value evaluates to 1 when value=0 and 0 when value≠0.
The second ! flips it, making !!value evaluate to 1 when value≠0 and 0 when value=0.

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

We may argue which way is better, but idiomatic, though for what I can tell by other answers archaic, would be if(!num).

Michael Krelin - hacker
  • 138,757
  • 24
  • 193
  • 173
0

For the compiler, it does not matter, of course. For the human reader it does. Since both forms are used by other human beings, you should get used to them and recognise them. Personally, I prefer the shortest form, which takes less time (less tokens, especially parenthesis) to read and understand. Especially:

if (!ptr) {}
if (!strcmp(a,b)) {}

are easyer to read than

if (ptr != NULL) {}
if (strcmp(a,b) == 0) {}
if (0 == strcmp()) {}

The last form makes me physically sick.

wildplasser
  • 43,142
  • 8
  • 66
  • 109