Skip to content

C Control Flow — If/Else, Switch, and Conditional Expressions Explained

DodaTech Updated 2026-06-28 8 min read

In this tutorial, you will learn about C Control Flow. We cover key concepts, practical examples, and best practices to help you master this topic.

C control flow statements let you make decisions in your code, executing different branches based on conditions using if/else for binary choices and switch for multiple discrete paths.

Why It Matters

Without control flow, every program would execute the same sequence of instructions regardless of input. Decision-making is what makes programs responsive and useful. Understanding how to structure conditions properly affects code readability, performance, and correctness. Poorly written control flow is the source of countless bugs.

Real-World Use

Every program uses control flow. A virus scanner checks file signatures against a database using if/else chains. A network server uses switch statements to handle different request types. Durga Antivirus Pro uses complex condition trees to classify files as safe, suspicious, or malicious.

What You Will Learn

  • If/else statements for binary and multi-way branching
  • Switch statements for discrete value selection
  • The conditional (ternary) operator for inline decisions
  • Nested conditions and best practices
  • Common pitfalls like dangling else and fallthrough

Learning Path

flowchart LR
  A[Operators] --> B[Control Flow
You are here] B --> C[Loops] C --> D[Arrays] D --> E[Strings] style B fill:#f90,color:#fff

The if Statement

The if statement executes a block of code only if a condition is true:

#include <stdio.h>

int main() {
    int temperature = 30;
    
    if (temperature > 25) {
        printf("It is hot today.\n");
    }
    
    // Without braces, only the next statement is conditional
    if (temperature > 25)
        printf("This runs only if condition is true.\n");
        printf("This ALWAYS runs.\n");  // Not part of if!
    
    return 0;
}

Expected output:

It is hot today.
This runs only if condition is true.
This ALWAYS runs.

Always use braces {} even for single statements. The dangling else problem and accidental misalignment are too common without them.

if/else and else if

#include <stdio.h>

int main() {
    int score = 85;
    
    if (score >= 90) {
        printf("Grade: A\n");
    } else if (score >= 80) {
        printf("Grade: B\n");
    } else if (score >= 70) {
        printf("Grade: C\n");
    } else if (score >= 60) {
        printf("Grade: D\n");
    } else {
        printf("Grade: F\n");
    }
    
    return 0;
}

Expected output: Grade: B

Evaluation Order

Conditions are evaluated in order from top to bottom. Once a condition is true, its block executes and the rest of the chain is skipped. This is why the order matters: if you check score >= 80 before score >= 90, a score of 95 would match the first condition and never reach the A grade.

The Conditional (Ternary) Operator

The ternary operator ? : is a compact way to write if/else for simple assignments:

#include <stdio.h>

int main() {
    int age = 20;
    const char *status = (age >= 18) ? "Adult" : "Minor";
    
    printf("Status: %s\n", status);
    
    // Nested ternary (use sparingly)
    int x = 15;
    const char *type = (x < 10) ? "Small" :
                       (x < 20) ? "Medium" : "Large";
    printf("Size: %s\n", type);
    
    // Ternary for value selection
    int a = 5, b = 10;
    int max = (a > b) ? a : b;
    printf("Max: %d\n", max);
    
    return 0;
}

Expected output:

Status: Adult
Size: Medium
Max: 10

The ternary operator is useful for inline decisions but should not replace readable if/else chains for complex logic.

The switch Statement

The switch statement selects among multiple discrete values:

#include <stdio.h>

int main() {
    int day = 3;  // Wednesday
    
    switch (day) {
        case 1:
            printf("Monday\n");
            break;
        case 2:
            printf("Tuesday\n");
            break;
        case 3:
            printf("Wednesday\n");
            break;
        case 4:
            printf("Thursday\n");
            break;
        case 5:
            printf("Friday\n");
            break;
        case 6:
        case 7:
            printf("Weekend!\n");
            break;
        default:
            printf("Invalid day\n");
            break;
    }
    
    return 0;
}

Expected output: Wednesday

Switch Rules

  • The controlling expression must be an integer type (including char and enum)
  • Each case must have a constant value
  • Without break, execution falls through to the next case
  • The default case handles all unmatched values
  • Case values must be unique

Fallthrough Behavior

Fallthrough is when a case does not end with break, so execution continues into the next case:

#include <stdio.h>

int main() {
    char grade = 'B';
    
    switch (grade) {
        case 'A':
            printf("Excellent!\n");
            break;
        case 'B':
        case 'C':
            printf("Good\n");  // Both B and C fall through here
            break;
        case 'D':
            printf("Passing\n");
            break;
        case 'F':
            printf("Failing\n");
            break;
    }
    
    return 0;
}

Expected output: Good

Fallthrough can be intentional and useful, but accidental fallthrough is a common bug. Some compilers warn about implicit fallthrough with -Wextra. Mark intentional fallthrough with a comment.

When to Use switch vs if/else

Situation Best Choice
Checking one variable against many constants switch
Complex conditions (ranges, combinations) if/else
Enum value selection switch
String comparisons if/else (no string switch)
Two or three simple cases if/else or ternary

Nested Conditions

You can nest if/else statements inside other if/else blocks:

#include <stdio.h>

int main() {
    int age = 25;
    int has_id = 1;
    
    if (age >= 21) {
        if (has_id) {
            printf("Welcome to the venue.\n");
        } else {
            printf("Please show ID.\n");
        }
    } else {
        printf("Sorry, you are too young.\n");
    }
    
    return 0;
}

Expected output: Welcome to the venue.

Deep nesting (more than 3 levels) makes code hard to read. Consider extracting nested conditions into separate functions.

The Dangling Else Problem

#include <stdio.h>

int main() {
    int x = 10, y = 5;
    
    // Which if does the else belong to?
    if (x > 5)
        if (y > 10)
            printf("Both conditions true\n");
    else
        printf("Something is false\n");  // Belongs to inner if!
    
    // Always use braces to make intent clear
    if (x > 5) {
        if (y > 10) {
            printf("Both conditions true\n");
        }
    } else {
        printf("Outer condition is false\n");
    }
    
    return 0;
}

In C, an else belongs to the nearest if that does not already have an else. Always use braces to make the association explicit.

Common Mistakes

1. Using Assignment Instead of Comparison

if (x = 5)  // Always true, assigns 5 to x

Use == for comparison. Enable compiler warnings with -Wall to catch this.

2. Forgetting break in switch

switch (x) {
    case 1:
        printf("One\n");
        // Missing break! Falls through to case 2
    case 2:
        printf("Two\n");
        break;
}

Always end each case with break unless fallthrough is intentional.

3. Testing Floating-Point Equality

double x = 0.1 + 0.2;
if (x == 0.3)  // May be false due to floating-point precision

Use an epsilon comparison: if (fabs(x - 0.3) < 0.0001).

4. Missing Default Case in switch

switch (day) {
    case MON:
    case TUE:
    case WED:
    case THU:
    case FRI:
        printf("Weekday\n");
        break;
    // No default -- unexpected values produce no output
}

Always include a default case for safety.

5. Checking Non-Boolean Values Directly

if (ptr)        // OK: checks for non-NULL
if (count)      // OK: checks for non-zero
if (ptr == 0)   // Avoid: better to write if (!ptr)

Practice Questions

  1. What is the output of if (0) { printf("yes"); } else { printf("no"); }? "no" -- because 0 is false in C.

  2. What happens if you omit the break in a switch case? Execution falls through to the next case (fallthrough).

  3. When should you use if/else instead of switch? When conditions involve ranges, complex expressions, or non-integer types.

  4. What is the dangling else problem? An else binds to the nearest if. Always use braces to make the association explicit.

  5. Challenge: Write a program that takes a month number (1-12) and prints the number of days in that month, accounting for leap years. Use a switch statement.

Mini Project: Simple Calculator

Build a command-line calculator using if/else and switch:

#include <stdio.h>

int main() {
    char op;
    double a, b;
    
    printf("Enter operator (+, -, *, /): ");
    scanf(" %c", &op);
    printf("Enter two operands: ");
    scanf("%lf %lf", &a, &b);
    
    switch (op) {
        case '+':
            printf("%.2f + %.2f = %.2f\n", a, b, a + b);
            break;
        case '-':
            printf("%.2f - %.2f = %.2f\n", a, b, a - b);
            break;
        case '*':
            printf("%.2f * %.2f = %.2f\n", a, b, a * b);
            break;
        case '/':
            if (b != 0) {
                printf("%.2f / %.2f = %.2f\n", a, b, a / b);
            } else {
                printf("Error: Division by zero\n");
            }
            break;
        default:
            printf("Error: Invalid operator\n");
    }
    
    return 0;
}

FAQ

Can I use strings in a switch statement?

No. C's switch requires integer types (int, char, enum). For strings, use if/else with strcmp().

What is the difference between if/else and switch performance?

Switch can be optimized into a jump table for dense integer cases, which is O(1). If/else is O(n) in the worst case.

Can I have multiple conditions in a single if?

Yes, combine them with logical operators: if (x > 0 && x < 100 && y != 0).

What does else if actually mean?

else if is not a separate keyword. It is an else statement followed immediately by an if statement. The compiler sees: else { if (...) { ... } }.

Is there a performance difference between if and ternary?

Modern compilers generate identical code for if/else and ternary in simple cases. Use whichever is more readable.

What is Next

Now that you understand control flow, proceed to Loops to learn about for, while, do-while, and loop control with break, continue, and goto.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro

Home Browse C