C Control Flow — If/Else, Switch, and Conditional Expressions Explained
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
casemust have a constant value - Without
break, execution falls through to the next case - The
defaultcase 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
What is the output of
if (0) { printf("yes"); } else { printf("no"); }? "no" -- because 0 is false in C.What happens if you omit the break in a switch case? Execution falls through to the next case (fallthrough).
When should you use if/else instead of switch? When conditions involve ranges, complex expressions, or non-integer types.
What is the dangling else problem? An else binds to the nearest if. Always use braces to make the association explicit.
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
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.