CLogical Operators

Logical Operators

Logical operators combine or invert boolean-style expressions. C provides three: && (logical AND), || (logical OR), and ! (logical NOT). They are used constantly in if conditions and loop guards to build compound tests out of simpler ones.

Operator

Meaning

Result

a && b

Logical AND

true only if both a and b are true

a || b

Logical OR

true if at least one of a, b is true

!a

Logical NOT

true if a is false, and vice versa

Truthiness in C
Zero is false, everything else is true
Classic C has no dedicated boolean type. Any expression used where a condition is expected is treated as false if it equals zero, and true otherwise — this includes negative numbers, which are truthy. Logical operators themselves always produce 1 or 0 as an int.

C
#include <stdio.h>

int main(void) {
    int a = 5, b = 0;

    printf("%d\n", a && b);  // 0 — b is falsy
    printf("%d\n", a || b);  // 1 — a is truthy
    printf("%d\n", !b);      // 1 — NOT of 0 is 1
    printf("%d\n", !a);      // 0 — NOT of a nonzero value is 0
    return 0;
}
Short-Circuit Evaluation
Both && and || stop evaluating as soon as the overall result is known. For &&, if the left operand is false, the right operand is never evaluated (since the whole expression must be false). For ||, if the left operand is true, the right operand is never evaluated. This is not just an optimization — code intentionally relies on it, for example to guard against invalid memory access.

C
#include <stdio.h>

int divisor = 0;

int isPositive(int n) {
    printf("isPositive called with %d\n", n);
    return n > 0;
}

int main(void) {
    /* Guard pattern: only dereference/divide if the left side allows it. */
    if (divisor != 0 && 100 / divisor > 1) {
        printf("division happened\n");
    } else {
        printf("skipped the division safely\n");
    }

    /* isPositive() is never called because the left side is already true. */
    if (1 || isPositive(-5)) {
        printf("short-circuited || — isPositive was NOT called\n");
    }

    return 0;
}
Logical vs Bitwise Operators
&& / || are not the same as & / |
This is one of the most common beginner mistakes in C specifically, because both the logical and bitwise operators exist and look almost identical. && and || operate on the truthiness of whole expressions and short-circuit. & and | operate bit-by-bit on the binary representation of integers and always evaluate both operands. Using a single & where you meant && usually still compiles — it just silently produces the wrong answer.

C
int a = 2; // binary 010
int b = 4; // binary 100

printf("%d\n", a && b);  // 1 — both are nonzero, so logically true
printf("%d\n", a & b);   // 0 — bitwise AND of 010 and 100 has no shared bits

int x = 5, y = 0;
if (x & y) {
    printf("won't print — bitwise AND, and y contributes no bits\n");
}
if (x && y) {
    printf("also won't print — y is falsy\n");
}
  • &&, ||, ! are the three logical operators; results are always 1 or 0

  • Zero is false, any nonzero value (including negatives) is true

  • && and || short-circuit — the right operand may never be evaluated

  • Do not confuse &&/|| (logical) with &/| (bitwise) — they look similar but do very different things