🧑🏽💻Intro to C Programming
Control Flow Statements
Study smarter with Fiveable
Get study guides, practice questions, and cheatsheets for all your subjects. Join 500,000+ students with a 96% pass rate.
Why This Matters
Control flow is the backbone of every C program you'll write. Without it, your code would execute line by line from top to bottom with no ability to make decisions, repeat tasks, or respond to different inputs. When you're tested on control flow, you're really being tested on your understanding of conditional logic, iteration patterns, and program execution order—concepts that appear in virtually every programming problem you'll encounter.
The key insight is this: control flow statements fall into distinct categories based on what they do—branching (choosing a path), looping (repeating code), and jumping (moving execution elsewhere). Don't just memorize syntax; know which statement solves which problem and why you'd choose one over another. That's what separates students who can write working code from those who just recognize keywords.
Conditional Branching: Making Decisions
These statements let your program choose different execution paths based on conditions. The core mechanism is Boolean evaluation—every condition resolves to either true (non-zero) or false (zero).
if Statement
- Simplest conditional—evaluates an expression and executes the code block only when the condition is true (non-zero)
- Syntax:
if (condition) { /* code */ }—parentheses around the condition are required, braces optional for single statements but always recommended - Foundation for all branching logic—understanding
ifis prerequisite to mastering every other control structure
if-else Statement
- Binary branching—provides two mutually exclusive paths, one for true and one for false conditions
- Syntax:
if (condition) { /* true path */ } else { /* false path */ }—exactly one block will always execute - Can be nested or chained with
else iffor multiple conditions, thoughswitchis often cleaner for many discrete values
switch Statement
- Multi-way branching—matches a single expression against multiple constant values efficiently
- Fall-through behavior—execution continues to the next case unless stopped by
break; this is both a feature and a common bug source - Requires integer-compatible types—works with
int,char, and enums, but not with strings or floating-point values
</>Cswitch (grade) { case 'A': printf("Excellent"); break; case 'B': printf("Good"); break; default: printf("Keep trying"); }
Compare: if-else chains vs. switch—both handle multiple conditions, but switch is cleaner and potentially faster when comparing one variable against many constant values. Use if-else when conditions involve ranges, comparisons, or non-constant expressions.
Iteration: Repeating Code
Loops execute a block of code multiple times. The key distinction is when the condition is checked and whether the number of iterations is known in advance.
for Loop
- Count-controlled iteration—combines initialization, condition, and update in one line:
for (init; condition; update) - Best when iterations are predetermined—use when you know exactly how many times to repeat (e.g., processing array elements)
- All three components are optional—
for (;;)creates an infinite loop, and any part can be omitted or contain multiple expressions
</>Cfor (int i = 0; i < 10; i++) { printf("%d ", i); }
while Loop
- Pre-test loop—evaluates condition before each iteration, meaning the body might never execute if initially false
- Best for unknown iteration counts—use when looping depends on dynamic conditions like user input or file reading
- Syntax:
while (condition) { /* body */ }—you must update the condition variable inside the loop or risk infinite loops
do-while Loop
- Post-test loop—evaluates condition after each iteration, guaranteeing the body executes at least once
- Syntax:
do { /* body */ } while (condition);—note the semicolon after the closing parenthesis (easy to forget!) - Ideal for input validation—when you need to prompt the user at least once before checking if their input is valid
Compare: while vs. do-while—both are condition-controlled loops, but while may skip the body entirely while do-while always runs once. If an exam asks about "guaranteed execution," do-while is your answer.
Compare: for vs. while—functionally equivalent (any for can be rewritten as while), but for is conventional when the iteration count is known, while when it depends on runtime conditions.
Jump Statements: Altering Flow
These statements transfer control to another point in the program. They interrupt normal sequential execution and should be used deliberately.
break Statement
- Immediate exit—terminates the nearest enclosing
for,while,do-while, orswitchstatement - Single-level only—breaks out of one loop; for nested loops, you'd need multiple breaks or a different approach
- Essential in switch—without
break, execution "falls through" to subsequent cases unintentionally
continue Statement
- Skip current iteration—jumps to the next iteration of the enclosing loop, bypassing remaining code in the body
- Works with all loop types—in
forloops, the update expression still executes; inwhile/do-while, control goes directly to the condition - Useful for filtering—skip processing certain elements without complex nested
ifstatements
</>Cfor (int i = 0; i < 10; i++) { if (i % 2 == 0) continue; // Skip even numbers printf("%d ", i); // Prints: 1 3 5 7 9 }
Compare: break vs. continue—break exits the loop entirely, continue skips to the next iteration. Both affect only the innermost loop, and both are commonly tested in trace-the-output questions.
goto Statement
- Unconditional jump—transfers control to a labeled statement anywhere in the same function
- Generally avoided—creates "spaghetti code" that's hard to read, debug, and maintain; most problems have cleaner solutions
- Rare valid use—breaking out of deeply nested loops where multiple
breakstatements would be awkward
return Statement
- Exits the function—immediately terminates execution of the current function and returns control to the caller
- Passes values back—
return value;sends a result to the calling code;return;exits void functions without a value - Can appear anywhere—useful for early exits when error conditions are detected, avoiding deeply nested logic
Compare: break vs. return—break exits a loop but continues the function, return exits the entire function. In main(), return also ends the program.
Quick Reference Table
| Concept | Best Examples |
|---|---|
| Binary decisions | if, if-else |
| Multi-way branching | switch, else if chains |
| Count-controlled loops | for |
| Condition-controlled loops | while, do-while |
| Guaranteed single execution | do-while |
| Early loop termination | break |
| Skip iteration | continue |
| Function exit | return |
| Unconditional jump (avoid) | goto |
Self-Check Questions
-
What's the key difference between
whileanddo-while? Write a scenario where choosing the wrong one would cause a bug. -
If you need to check a variable against the values 1, 2, 3, 4, and 5, which control structure would be most appropriate—
if-elsechain orswitch? Why? -
Compare
breakandcontinue: what happens to loop execution after each? In aforloop, does the update expression run aftercontinue? -
Convert this
forloop to an equivalentwhileloop:</>Cfor (int i = 0; i < n; i++) { printf("%d", i); } -
A function needs to validate user input, prompting repeatedly until valid data is entered. Which loop type is most appropriate, and why would the alternatives be problematic?