CNested Conditionals

Nested Conditionals

A nested conditional is simply an if statement placed inside the body of another if (or else) statement. Nesting lets you express "check this, and only if that is true, also check this other thing" — which comes up constantly when a decision genuinely depends on more than one condition being satisfied in sequence.
Basic Example

C
#include <stdio.h>

int main(void) {
    int age = 25;
    int hasLicense = 1;

    if (age >= 18) {
        if (hasLicense) {
            printf("You may drive.\n");
        } else {
            printf("You need a license first.\n");
        }
    } else {
        printf("You are too young to drive.\n");
    }

    return 0;
}
Readability Concerns With Deep Nesting
Nesting is a powerful tool, but it does not scale well. Each level of nesting adds another layer of indentation and another condition the reader has to hold in their head simultaneously. Beyond two or three levels, code becomes what is often called the "arrow" or "pyramid of doom"— a shape where the actual logic is buried far to the right, and it is easy to lose track of which brace closes which condition.

C
// Deep nesting is hard to follow: four levels of indentation
// before we even reach the real work.
if (user != NULL) {
    if (user->isActive) {
        if (user->hasPermission) {
            if (resource != NULL) {
                processRequest(user, resource);
            }
        }
    }
}
Warning
Deeply nested conditionals are a common source of bugs: it becomes easy to put a statement inside the wrong block, forget an else at the correct level, or misjudge which condition actually guards a given line. Treat more than two or three levels of nesting as a signal to refactor.
Flattening With Guard Clauses
A guard clause is an early check, usually near the top of a function, that handles an invalid or uninteresting case immediately (often with return, continue, orbreak) instead of wrapping the rest of the function in another level of if. Each guard clause removes one level of nesting, so the "main" logic of the function ends up flat and easy to read.

C
/* BEFORE: nested conditionals, four levels deep */
void processRequestNested(User *user, Resource *resource) {
    if (user != NULL) {
        if (user->isActive) {
            if (user->hasPermission) {
                if (resource != NULL) {
                    doWork(user, resource);
                }
            }
        }
    }
}

/* AFTER: guard clauses flatten the same logic to a single level */
void processRequestFlat(User *user, Resource *resource) {
    if (user == NULL) return;
    if (!user->isActive) return;
    if (!user->hasPermission) return;
    if (resource == NULL) return;

    doWork(user, resource);
}
Note
Both versions above behave identically. The guard-clause version is preferred in most real-world C code because each precondition is checked once, in isolation, and the reader never has to mentally track more than one condition at a time to understand what eventually happens.
When Nesting Is Still the Right Choice

Not all nesting is bad. When a decision genuinely branches into several distinct outcomes at each level (rather than repeatedly bailing out on invalid input), a shallow nest of two levels is often the clearest way to express it. The goal is not to eliminate nesting entirely, but to avoid nesting so deep that the logic becomes hard to trace.

Tip
A useful rule of thumb: if you can rewrite an inner if as an early return/continue/break without changing behavior, do it. If the branches genuinely represent different outcomes that all need to keep executing in context, a small amount of nesting is fine.
Key Points
  • Nested conditionals let you express dependent checks, but each level adds cognitive overhead for the reader.

  • Deep nesting (the "pyramid of doom") makes it easy to misplace statements or lose track of which condition guards them.

  • Guard clauses -- early returns/continues/breaks for invalid or uninteresting cases -- flatten nested conditionals into a linear sequence.

  • Aim to keep nesting to two or three levels at most; beyond that, look for a guard-clause refactor.