# Loops and Blocks and Labels

**URL:** <https://ziggit.dev/t/loops-and-blocks-and-labels/15456>\
**Category:** Explain\
**Tags:** language\
**Created:** [May 11, 2026, 10:14am UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456 "2026-05-11T10:14:22Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![asibahi](https://ziggit.dev/user_avatar/ziggit.dev/asibahi/32/5416_2.png) [@asibahi](https://ziggit.dev/u/asibahi)\
**Post date:** [May 11, 2026, 10:14am UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/1 "2026-05-11T10:14:22Z")

</div>

Just a funny I noticed:

What do you think the output of this program would be:

```zig
const std = @import("std");
pub fn main() !void {
	var i: u32 = 0;
	while (i < 6) : (i += 1) b: {
		std.debug.print("BLOCK\n", .{});
		if (i >= 3) break :b;

		std.debug.print("LOOP\n", .{});
	} else {
		std.debug.print("ELSE\n", .{});
	}
}

```

In other words, does breaking out of the `then` block break out of the loop?

(obviously you can just run the program I am just curious about everyone’s intuition)

---

<div class="post-metadata">

**Author:** ![Anthon](https://ziggit.dev/user_avatar/ziggit.dev/anthon/32/8967_2.png) [@Anthon](https://ziggit.dev/u/Anthon)\
**Post date:** [May 11, 2026, 10:29am UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/2 "2026-05-11T10:29:38Z")

</div>

Isn’t the `break :b;` effectively functioning as a continue?

I would expect 6x BLOCK, the first 3 of which followed by LOOP (until the break/continue takes effect) and then the ELSE

---

<div class="post-metadata">

**Author:** ![matklad](https://ziggit.dev/user_avatar/ziggit.dev/matklad/32/2462_2.png) [@matklad](https://ziggit.dev/u/matklad)\
**Post date:** [May 11, 2026, 10:29am UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/3 "2026-05-11T10:29:43Z")

</div>

It’s the same as if it said `continue`, right? Don’t show this to andrew, he might remove the keyword for redundancy then 🤣

---

<div class="post-metadata">

**Author:** ![Anthon](https://ziggit.dev/user_avatar/ziggit.dev/anthon/32/8967_2.png) [@Anthon](https://ziggit.dev/u/Anthon)\
**Post date:** [May 11, 2026, 10:31am UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/4 "2026-05-11T10:31:45Z")

</div>

> [@matklad](#):
>
> Don’t show this to andrew, he might remove the keyword for redundancy then

Lets quickly flag the post as inappropriate

---

<div class="post-metadata">

**Author:** ![npc1054657282](https://ziggit.dev/user_avatar/ziggit.dev/npc1054657282/32/5790_2.png) [@npc1054657282](https://ziggit.dev/u/npc1054657282)\
**Post date:** [May 11, 2026, 10:33am UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/5 "2026-05-11T10:33:55Z")

</div>

I think it makes sense to remove `continue`, even though this keyword has been used to implement state machines in switch statements.

---

<div class="post-metadata">

**Author:** ![MeKaLu](https://ziggit.dev/user_avatar/ziggit.dev/mekalu/32/6360_2.png) [@MeKaLu](https://ziggit.dev/u/MeKaLu)\
**Post date:** [May 11, 2026, 11:15am UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/6 "2026-05-11T11:15:27Z")

</div>

Oh no not another cursed language feature… I love it.

---

<div class="post-metadata">

**Author:** ![whitehexagon](https://ziggit.dev/user_avatar/ziggit.dev/whitehexagon/32/5917_2.png) [@whitehexagon](https://ziggit.dev/u/whitehexagon)\
**Post date:** [May 11, 2026, 11:43am UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/7 "2026-05-11T11:43:57Z")

</div>

🙂 as long as we can rename break to goto…

---

<div class="post-metadata">

**Author:** ![00JCIV00](https://ziggit.dev/user_avatar/ziggit.dev/00jciv00/32/1069_2.png) [@00JCIV00](https://ziggit.dev/u/00JCIV00)\
**Post date:** [May 11, 2026, 2:09pm UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/8 "2026-05-11T14:09:06Z")

</div>

This is exactly how I “continue” from `inline for` loops.

[Example](https://ziggit.dev/t/comptime-control-flow-inside-runtime-block/4962/8)

---

<div class="post-metadata">

**Author:** ![npc1054657282](https://ziggit.dev/user_avatar/ziggit.dev/npc1054657282/32/5790_2.png) [@npc1054657282](https://ziggit.dev/u/npc1054657282)\
**Post date:** [May 11, 2026, 6:42pm UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/9 "2026-05-11T18:42:58Z")

</div>

The semantics are vastly different: `goto` refers to jumping to a label, whereas Zig’s `break` refers to leaving the code block where the label is located.

---

<div class="post-metadata">

**Author:** ![asibahi](https://ziggit.dev/user_avatar/ziggit.dev/asibahi/32/5416_2.png) [@asibahi](https://ziggit.dev/u/asibahi)\
**Post date:** [May 11, 2026, 6:49pm UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/10 "2026-05-11T18:49:47Z")

</div>

Obviously the solution is to change the block’s label location to the end of the block.

```zig
{
    do();
    if (cond) goto :label;
    domore();
} :label
```

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [May 11, 2026, 7:04pm UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/11 "2026-05-11T19:04:48Z")

</div>

omg… i can’t read this. `while...else...`

---

<div class="post-metadata">

**Author:** ![spiffyk](https://ziggit.dev/user_avatar/ziggit.dev/spiffyk/32/7202_2.png) [@spiffyk](https://ziggit.dev/u/spiffyk)\
**Post date:** [May 11, 2026, 7:10pm UTC](https://ziggit.dev/t/loops-and-blocks-and-labels/15456/12 "2026-05-11T19:10:26Z")

</div>

OR, hear me out, make this work:

```zig
var i: u32 = 0;
block: {
	std.debug.print("{d}\n", .{i});
	if (i < 10)
		continue :block;
}

```

so that the `continue` makes it go back to the beginning of the `block`.

And remove `for` and `while` in its favour 🙃

/j
