`const` and `var`
Zig has two kinds of variable declarations:
const and var
Zig has two kinds of variable declarations:
const
and
var
A const declaration creates a name whose value cannot change.
const year = 2026;
A var declaration creates a mutable variable.
var count = 0;
The difference is important. Zig prefers immutability when possible.
Consider:
const std = @import("std");
pub fn main() void {
const x = 10;
std.debug.print("{d}\n", .{x});
}
This program is correct.
Now try to assign a new value:
const x = 10;
x = 20;
The compiler reports an error. A constant cannot be changed after initialization.
A mutable variable may be assigned another value:
const std = @import("std");
pub fn main() void {
var n = 1;
n = 2;
n = 3;
std.debug.print("{d}\n", .{n});
}
The output is:
3
A declaration must always be initialized.
This is valid:
const x = 5;
var y = 10;
This is not:
var n; // error
Zig does not allow uninitialized local variables unless the programmer explicitly asks for undefined memory.
var n: i32 = undefined;
undefined means the value is not initialized. Reading it before writing a value is an error.
Usually you should initialize variables normally.
var n: i32 = 0;
The compiler checks whether a mutable variable is actually mutated.
var x = 10;
If x is never changed, the compiler may suggest using const instead.
This helps keep programs simpler and safer.
A constant does not mean the data itself is always immutable. It means the binding cannot be changed.
Consider:
var data = [_]u8{ 1, 2, 3 };
const slice = data[0..];
slice always refers to the same slice, but the underlying array may still change.
data[0] = 9;
Now slice[0] is also 9.
The constant applies to the name, not necessarily to all reachable memory.
You may also create constant pointers and mutable pointers.
var x: i32 = 10;
const p = &x;
p always points to the same location.
But the value at that location may still change:
p.* = 20;
The expression:
p.*
means “the value pointed to by p”.
A mutable variable is useful when a value changes over time.
var sum: i32 = 0;
sum += 1;
sum += 2;
sum += 3;
A constant is useful when a value should stay fixed.
const max_users = 100;
Most declarations in Zig programs are constants.
This style has several advantages:
- values cannot change accidentally
- the compiler can reason more precisely
- code is easier to read
- fewer states exist in the program
A small example:
const std = @import("std");
pub fn main() void {
const width = 80;
const height = 25;
const area = width * height;
std.debug.print("{d}\n", .{area});
}
None of these values need mutation, so const is appropriate.
Now consider a loop:
const std = @import("std");
pub fn main() void {
var i: usize = 0;
while (i < 5) : (i += 1) {
std.debug.print("{d}\n", .{i});
}
}
Here i changes during execution, so it must be declared with var.
Use const by default. Use var only when mutation is necessary.
Exercises:
-
Declare a constant named
piwith value3.14. -
Declare a variable named
count, increment it three times, then print it. -
Write a program that swaps the values of two mutable variables.
-
Create a mutable array and a constant slice that refers to it. Modify the array and print the slice contents.
-
Declare a variable with
undefined, assign a value later, then print it.