Logical AND

Performs a logical boolean AND-ing of the two operands returning 1 if both of the operands are non-zero. The logical AND operator is of type int.

0 && 0  /* Returns 0. */
0 && 1  /* Returns 0. */
2 && 0  /* Returns 0. */
2 && 3  /* Returns 1. */

Logical OR

Performs a logical boolean OR-ing of the two operands returning 1 if any of the operands are non-zero. The logical OR operator is of type int.

0 || 0  /* Returns 0. */
0 || 1  /* Returns 1.  */
2 || 0  /* Returns 1.  */
2 || 3  /* Returns 1.  */

Logical NOT

Performs a logical negation. The logical NOT operator is of type int. The NOT operator checks if at least one bit is equal to 1, if so it returns 0. Else it returns 1;

!1 /* Returns 0. */
!5 /* Returns 0. */
!0 /* Returns 1. */

Short-Circuit Evaluation

There are some crucial properties common to both && and ||:

This means that:

This is important as it permits you to write code such as:

const char *name_for_value(int value)
{
    static const char *names[] = { "zero", "one", "two", "three", };
    enum { NUM_NAMES = sizeof(names) / sizeof(names[0]) };
    return (value >= 0 && value < NUM_NAMES) ? names[value] : "infinity";
}

If a negative value is passed to the function, the value >= 0 term evaluates to false and the value < NUM_NAMES term is not evaluated.