Logical NOT in C – Why !0 Is 1 and ~0 Is -1

The logical NOT operator ! flips truth: true becomes false, false becomes true. Sounds trivial — until the options include -1 and you have to remember which NOT is which. This question from our C Programming Quiz App separates ! from its bitwise cousin ~.

The Quiz Question

int x = 0;
printf("%d", !x);

What is printed by this code?

  1. 0
  2. 1
  3. -1
  4. Compile error

The Correct Answer: 1

In C, 0 is false and anything nonzero is true. ! inverts that verdict and always yields a clean int 1 or 0: since x is 0 (false), !x is 1 (true). Verified on gcc 13.3 and Apple clang 21, warning-free:

$ gcc -Wall -Wextra not.c && ./a.out
1

And the flip works in both directions — from the same verified run:

printf("%d\n", !x);     /* 1 — NOT false        */
printf("%d\n", !5);     /* 0 — NOT true         */
printf("%d\n", !!42);   /* 1 — double NOT       */

Why Each Wrong Answer Is Wrong

Why not 0?

0 is the input, not the output — ! inverts. Answering 0 either ignores the operator or assumes NOT-of-zero is “still nothing”. !0 is the very definition of true in C: 1.

Why not -1?

-1 is what the bitwise NOT gives. ~ flips every individual bit, and flipping all bits of 0 sets all 32 of them — which is -1 in two’s complement. We verified the contrast on both compilers:

printf("%d\n", ~0);   /* -1 — all bits set (bitwise NOT)  */
printf("%d\n", ~5);   /* -6 — every bit of 5 flipped      */

! asks one question (“is it zero?”) and answers 0 or 1. ~ performs 32 tiny flips and can produce any value. Same word — NOT — two completely different operators.

Why not “Compile error”?

! applies to any scalar — integers, floats, pointers. !p on a pointer is the idiomatic NULL test. Nothing here is even warning-worthy.

The !! Idiom

Applying NOT twice looks pointless but has a real job: it normalizes any truthy value to exactly 1. !!42!0 → 1. You’ll meet it where an API needs a strict 0-or-1 — storing into a bitfield, returning a “boolean” from a function pre-C99, or comparing two truth values for equality (!!a == !!b) where raw values like 5 and 42 would compare unequal despite both being “true”. It’s the same normalization that || and && perform on their results, as covered in the logical OR post.

Frequently Asked Questions

What is the difference between ! and ~ in C?

! is logical NOT: it yields 1 if the operand is zero, 0 otherwise — !0 is 1. ~ is bitwise NOT: it flips every bit — ~0 is -1 (all bits set). They agree on almost nothing.

What does !!x do in C?

Normalizes x to exactly 0 or 1: !!0 is 0, and !!x for any nonzero x is 1. Useful when a strict boolean 0/1 is required.

Can I apply ! to a pointer?

Yes — !p yields 1 when p is NULL and 0 otherwise, which is why if (!p) is the standard null-check idiom.

Related Reading

Recommended Books

This question is #64 in the C Programming Quiz App — 155 questions with explanations covering operators, pointers, memory, and more.
Download on Google Play →

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>