Variables
A variable is a unit of Memory storage.
Variables are never allowed to shadow identifiers from an outer scope.
It is generally preferable to use const
rather than var
when declaring a variable. This causes less work for both humans and computers to do when reading code, and creates more optimization opportunities.
Global Variables
Global variables are considered to be a top level declaration, which means that they are order-independent and lazily analyzed. The initialization value of global variables is implicitly comptime. If a global variable is const
then its value is comptime
-known, otherwise it is runtime-known.
global_variables.zig
var y: i32 = add(10, x);
const x: i32 = add(12, 34);
test "global variables" {
expect(x == 46);
expect(y == 56);
}
fn add(a: i32, b: i32) i32 {
return a + b;
}
const std = @import("std");
const expect = std.testing.expect;
$ zig test global_variables.zig
1/1 test "global variables"... OK
All 1 tests passed.
Global variables may be declared inside a struct, union, or enum:
namespaced_global.zig
const std = @import("std");
const expect = std.testing.expect;
test "namespaced global variable" {
expect(foo() == 1235);
expect(foo() == 1236);
}
fn foo() i32 {
const S = struct {
var x: i32 = 1234;
};
S.x += 1;
return S.x;
}
$ zig test namespaced_global.zig
1/1 test "namespaced global variable"... OK
All 1 tests passed.
The extern
keyword can be used to link against a variable that is exported from another object. The export
keyword or @export builtin function can be used to make a variable available to other objects at link time. In both cases, the type of the variable must be C ABI compatible.
See also:
Thread Local Variables
A variable may be specified to be a thread-local variable using the threadlocal
keyword:
tls.zig
const std = @import("std");
const assert = std.debug.assert;
threadlocal var x: i32 = 1234;
test "thread local storage" {
const thread1 = try std.Thread.spawn({}, testTls);
const thread2 = try std.Thread.spawn({}, testTls);
testTls({});
thread1.wait();
thread2.wait();
}
fn testTls(context: void) void {
assert(x == 1234);
x += 1;
assert(x == 1235);
}
$ zig test tls.zig
1/1 test "thread local storage"... OK
All 1 tests passed.
For Single Threaded Builds, all thread local variables are treated as Global Variables.
Thread local variables may not be const
.
Local Variables
Local variables occur inside Functions, comptime blocks, and @cImport blocks.
When a local variable is const
, it means that after initialization, the variable’s value will not change. If the initialization value of a const
variable is comptime-known, then the variable is also comptime
-known.
A local variable may be qualified with the comptime
keyword. This causes the variable’s value to be comptime
-known, and all loads and stores of the variable to happen during semantic analysis of the program, rather than at runtime. All variables declared in a comptime
expression are implicitly comptime
variables.
comptime_vars.zig
const std = @import("std");
const expect = std.testing.expect;
test "comptime vars" {
var x: i32 = 1;
comptime var y: i32 = 1;
x += 1;
y += 1;
expect(x == 2);
expect(y == 2);
if (y != 2) {
// This compile error never triggers because y is a comptime variable,
// and so `y != 2` is a comptime value, and this if is statically evaluated.
@compileError("wrong y value");
}
}
$ zig test comptime_vars.zig
1/1 test "comptime vars"... OK
All 1 tests passed.