ZigBasics

Zig Control Flow: Mastering Logic

TT
TopicTrick Team
Zig Control Flow: Mastering Logic

Zig Control Flow: Mastering Logic

In many languages (Java, JavaScript), "Control Flow" can be deceptively hidden by "Exceptions" or "Iterators." In Zig, every jump is explicit. If you see a while loop, you know exactly what the CPU is doing. If you see an if, you know exactly where the branch leads.

In this 1,500+ word guide, we will explore the "Zig Way" of writing logic. We will master the while Continue Expression, the switch Exhaustiveness, and the unique way Zig uses if as an Expression to replace the ternaries of legacy languages. We will also dive into the high-performance world of Labeled Blocks and Inline Loops that allow you to unroll logic at compile-time.


1. If-Statements: Everything is an Expression

In C and Java, if is a statement—a block of code that does something but has no "Value." In Zig, if is an expression. It can return a result.

Goodbye Ternary Operator

Zig does not have the condition ? a : b syntax. Why? Because if as an expression is more readable and less prone to errors.

zig

If with Payload Capture

One of Zig's most powerful features is capturing data directly in the if head. This is most commonly used with Optional Types (Module 3) and Error Unions (Module 8).

zig

2. Branch Prediction Physics: The Cost of the if

To the software, an if is a choice. To the hardware, an if is a Pipeline Stall risk.

The Branch Predictor Mirror

  • The Concept: Modern CPUs (like the M4 or x86_64) use Branch Prediction to guess which way an if will go before it actually executes.
  • The Physics: If the CPU guesses correctly, the code runs at full speed. If it guesses incorrectly (a "Branch Mispredict"), the CPU must flush its entire execution pipeline, wasting 10-20 clock cycles.
  • Zig's Advantage: Zig provides the @expect and @setRuntimeSafety(false) builtins to help the compiler generate more "Predictable" machine code, ensuring that your high-frequency branches align with the CPU's speculative execution logic.

3. While Loops: The "Continue" Expression

A while loop in Zig has a specialized syntax called the Continue Expression. This is denoted by the : after the loop condition.

zig

The Safety Advantage

In C++, if you call continue in a while loop, you might accidentally skip the "Increment" step, leading to an Infinite Loop. In Zig, the code after the colon is guaranteed to run at the end of every iteration, matching the reliability of a for loop in other languages but with the flexibility of a conditional while.

While with Else

Did you know a while loop can have an else block?

  • If the loop condition is false from the very start, the else block executes.
  • This is useful for "Search" logic: "While looking for X... else (if not found) do Y."

3. For Loops: The Multi-Stream Engine

for loops in Zig are designed for iterating over Slices and Arrays. They are not "C-style" loops (use while for those).

Parallel Iteration

In 2026, Zig developers rarely iterate over one thing at a time. You can iterate over multiple slices of the same length simultaneously:

zig

The 0.. Shorthand: This is an "Infinite Range." It allows you to get the current index of the loop without managing a separate var i variable.

Pointer Captures

If you want to Modify the data in the array, you must capture it as a pointer using *:

zig

4. Switch Expressions: The Guard of Exhaustiveness

A switch in Zig is your primary defense against "Outdated Logic."

The Exhaustiveness Requirement

If you are switching on an Enum, you MUST handle every possible case. If you add a new Status.Pending to your enum but forget to update your switch block, Zig will refuse to compile your program.

zig

Advanced Switch Patterns

  • Ranges: 'a'...'z' => std.debug.print("Lowercase", .{})
  • Multiple Cases: .red, .blue => ...
  • Default: else => ... (Use this sparingly; explicit cases are always safer).

5. Labeled Blocks and Breaks

Have you ever wanted to "Break" out of three nested loops at once? In other languages, you need a "Flag" variable. In Zig, you use Labels.

zig

Labels aren't just for loops. You can label any block { ... } and use break :label value to return a value from that block. This effectively allows you to create "Anonymous Functions" or complex logic blocks that act like expressions.


6. Loop Unrolling: Defeating the Instruction Cache

Binary size is often traded for speed. Marking a loop as inline in Zig is a direct instruction to the compiler to perform Loop Unrolling.

The Cache Mirror

  • The Process: a normal for loop generates a JMP instruction back to the start. The CPU must re-read the loop instructions from the L1 Instruction Cache.
  • The Physics: An inline loop removes the JMP. The code is laid out linearly in memory.
  • The Optimization: This reduces "Branch Pressure" on the hardware. However, if the loop is too large, it can overflow the L1 cache, causing a "Cache Miss" that actually slows the program down.
  • The Rule: Use inline for loops with a small, known number of iterations (e.g., < 16) to maximize the "Throughput" of your silicon.

Control Flow is the "Movement" of your software. By mastering the explicit jumps of Zig and the safety of exhaustive switching, you gain the ability to build logic that is 100% predictable and indestructible. You graduate from "Guessing the flow" to "Architecting Execution."


Phase 5: Execution Checklist

  • Refactor your assignment logic to use if as an expression instead of mutable var.
  • Implement a Continue Expression in a while loop to guarantee state increments.
  • Use Labeled Breaks to eliminate at least one boolean "Flag" in your nested loops.
  • Identify a critical loop (e.g., a pixel filter) and test the performance of an inline for.
  • Audit your switch statements: Ensure no else => fallback exists for Enum switches to maintain compile-time exhaustiveness.

Read next: Enums and Unions: The Logic of Choice →


Part of the Zig Mastery Course — engineering the flow.