Zig提供三种变量声明方式,每种都有明确的语义:
const std = @import("std");
pub fn main() !void {
// const: 不可变绑定——声明后不可修改
const pi: f64 = 3.14159265358979;
// var: 可变绑定——可以重新赋值
var counter: u32 = 0;
counter += 1;
// 空白标识符:丢弃值(必须使用,Zig不允许未使用变量)
_ = pi; // 显式忽略pi的值
// 类型推断:Zig可以自动推断类型
const x = 42; // 推断为 comptime_int
const y: i64 = 42; // 显式类型 i64
const z: usize = 42; // 显式类型 usize
std.debug.print("counter = {}, x = {}\n", .{counter, x});
}
x_ 后缀表示"未使用"变量(替代 _ = x)const snake_case_var = 10; // 变量
const MyType = u32; // 类型别名
var unused_x_ = 5; // 带未使用后缀
Zig提供完整的有符号和无符号整数类型:
| 类型 | 范围 | 大小 |
|---|---|---|
i8 | -128 ~ 127 | 1字节 |
u8 | 0 ~ 255 | 1字节 |
i16 | -32768 ~ 32767 | 2字节 |
u16 | 0 ~ 65535 | 2字节 |
i32 | -2³¹ ~ 2³¹-1 | 4字节 |
u32 | 0 ~ 2³²-1 | 4字节 |
i64 | -2⁶³ ~ 2⁶³-1 | 8字节 |
u64 | 0 ~ 2⁶⁴-1 | 8字节 |
i128 | -2¹²⁷ ~ 2¹²⁷-1 | 16字节 |
u128 | 0 ~ 2¹²⁸-1 | 16字节 |
isize | 指针大小有符号 | 平台相关 |
usize | 指针大小无符号 | 平台相关 |
Zig支持任意位宽的整数类型:
const a: i7 = -64; // 7位有符号整数
const b: u23 = 8388607; // 23位无符号整数
const c: i1 = -1; // 1位有符号整数(-1或0)
const d: u0 = 0; // 0位整数(只能为0,编译期常量)
const std = @import("std");
pub fn main() !void {
var x: u8 = 200;
var y: u8 = 100;
// 标准运算——Debug模式溢出会panic
const sum = x + y; // Debug: panic! ReleaseFast: 回绕
// 显式回绕运算(所有模式都回绕)
const wrapped = std.math.add(u8, x, y) catch 0;
// 饱和运算——超过范围取边界值
const sat_add = std.math.clamp(@as(u16, x) + y, 0, 255);
// 使用溢出运算符
const ov = @addWithOverflow(x, y);
if (ov[1] != 0) {
std.debug.print("溢出! 结果={}\n", .{ov[0]});
}
// 宽化运算——自动提升到更大类型
const wide: u16 = @as(u16, x) + y;
std.debug.print("安全求和: {}\n", .{wide});
_ = sum; _ = wrapped; _ = sat_add;
}
const a: i32 = 42;
// 宽化转换(小→大,安全)
const b: i64 = @intCast(a);
// 窄化转换(大→小,可能截断)
const c: i8 = @intCast(a); // Debug模式下超出范围会panic
// 有符号↔无符号
const d: u32 = @intCast(a); // 负数会panic
const e: i32 = @intCast(d); // 超出i32范围会panic
// 位重解释(不改变底层位模式)
const f: u32 = @bitCast(a);
// 指针→整数
const ptr_val = @intFromPtr(&a);
// 浮点→整数(截断小数)
const g: i32 = @intFromFloat(3.7); // g = 3
const std = @import("std");
pub fn main() !void {
const f16_val: f16 = 3.14; // 半精度(16位)
const f32_val: f32 = 3.14159; // 单精度(32位)
const f64_val: f64 = 3.14159265358979; // 双精度(64位)
const f80_val: f80 = 3.14159265358979; // 扩展精度(80位)
const f128_val: f128 = 3.141592653589793238; // 四精度(128位)
// 浮点运算
const result = f32_val * 2.0 + 1.0;
// 数学函数
const sqrt_val = std.math.sqrt(f64_val);
const sin_val = std.math.sin(f64_val);
const abs_val = std.math.fabs(f64_val);
// 浮点→整数
const int_val: i32 = @intFromFloat(f64_val);
// 整数→浮点
const float_from_int: f64 = @floatFromInt(@as(i32, 42));
std.debug.print("sqrt(π) = {d:.6}\n", .{sqrt_val});
std.debug.print("int from float = {}\n", .{int_val});
_ = f16_val; _ = f80_val; _ = f128_val; _ = result;
_ = sin_val; _ = abs_val; _ = float_from_int;
}
const std = @import("std");
pub fn main() !void {
const is_true: bool = true;
const is_false: bool = false;
// 布尔运算
const and_result = is_true and is_false; // 逻辑与
const or_result = is_true or is_false; // 逻辑或
const not_result = !is_true; // 逻辑非
// 布尔→整数
const bool_to_int: u1 = @intFromBool(is_true);
std.debug.print("true AND false = {}\n", .{and_result});
std.debug.print("bool as int = {}\n", .{bool_to_int});
_ = or_result; _ = not_result;
}
Zig用?T表示可能为null的值——这是类型系统级别的空安全:
const std = @import("std");
pub fn main() !void {
// 可选整数——可以是整数或null
var maybe_num: ?i32 = 42;
maybe_num = null; // 可以赋值为null
// 检查可选值
if (maybe_num) |num| {
std.debug.print("值存在: {}\n", .{num});
} else {
std.debug.print("值为null\n", .{});
}
// orelse提供默认值
const value = maybe_num orelse 0;
// 可选指针
var x: i32 = 100;
var ptr: ?*i32 = &x;
ptr = null;
// 可选解包——.?操作符
maybe_num = 99;
const unwrapped = maybe_num.?; // 如果是null则panic
std.debug.print("value={}, unwrapped={}\n", .{value, unwrapped});
_ = ptr;
}
Zig没有专门的字符串类型——字符串是[]const u8(u8常量切片):
const std = @import("std");
pub fn main() !void {
// 字符串字面量——编译期存在的[]const u8
const greeting = "Hello, Zig!";
// 字符串长度(不包括末尾的0)
std.debug.print("长度: {}\n", .{greeting.len});
// 单字节访问
std.debug.print("第一个字节: 0x{x:02}\n", .{greeting[0]});
// 遍历字节
for (greeting) |byte| {
std.debug.print("{c}", .{byte});
}
std.debug.print("\n", .{});
// 多行字符串
const multi_line =
\\第一行
\\第二行
\\第三行
;
// 字符串连接(编译期)
const combined = "Hello" ++ " " ++ "World";
// 字符串格式化
const name = "Zig";
const version = 0.13;
std.debug.print("{s} v{d:.2}\n", .{ name, version });
_ = multi_line; _ = combined;
}
const std = @import("std");
const unicode = std.unicode;
pub fn main() !void {
const chinese = "你好世界";
// 字节长度 vs Unicode码点数
std.debug.print("字节长度: {}\n", .{chinese.len}); // 12(每个汉字3字节)
// 迭代UTF-8码点
var iter = unicode.Utf8Iterator{ .bytes = chinese, .i = 0 };
var count: usize = 0;
while (iter.nextCodepoint()) |cp| {
count += 1;
std.debug.print("码点: U+{X:0>4}\n", .{cp});
}
std.debug.print("Unicode字符数: {}\n", .{count}); // 4
}
const std = @import("std");
pub fn main() !void {
// 固定大小数组
const arr = [5]i32{ 1, 2, 3, 4, 5 };
// 编译期推断大小
const inferred = .{ 10, 20, 30 };
// 重复值初始化
const zeros = [100]u8{0} ** 1;
// 数组到切片
const slice: []const i32 = &arr;
// 遍历数组
for (arr, 0..) |value, index| {
std.debug.print("arr[{}] = {}\n", .{ index, value });
}
// 多维数组
const matrix = [2][3]f32{
.{ 1.0, 2.0, 3.0 },
.{ 4.0, 5.0, 6.0 },
};
std.debug.print("matrix[1][2] = {d:.1}\n", .{matrix[1][2]});
// 数组拼接(编译期)
const a = [3]u8{ 1, 2, 3 };
const b = [2]u8{ 4, 5 };
const c = a ++ b; // [5]u8{ 1, 2, 3, 4, 5 }
_ = inferred; _ = zeros; _ = slice; _ = c;
}
const std = @import("std");
pub fn main() !void {
var arr = [5]i32{ 10, 20, 30, 40, 50 };
// 切片语法
const full = arr[0..]; // 全部元素
const part = arr[1..3]; // arr[1], arr[2]
const from = arr[2..]; // 从索引2开始
// 切片属性
std.debug.print("len={}, ptr={*}\n", .{ full.len, full.ptr });
// 运行时切片(需要运行时索引)
var start: usize = 1;
const runtime_slice = arr[start..];
// 切片重新赋值
var mutable_slice = arr[0..];
mutable_slice[0] = 99;
_ = part; _ = from; _ = runtime_slice;
std.debug.print("arr[0] = {}\n", .{arr[0]});
}
Zig内置SIMD向量支持,无需外部库:
const std = @import("std");
pub fn main() !void {
// 4个f32的SIMD向量
const v1 = @Vector(4, f32){ 1.0, 2.0, 3.0, 4.0 };
const v2 = @Vector(4, f32){ 5.0, 6.0, 7.0, 8.0 };
// 向量运算——一条指令同时处理4个值
const sum = v1 + v2; // [6,8,10,12]
const product = v1 * v2; // [5,12,21,32]
// 向量与标量运算
const scaled = v1 * @splat(2.0); // [2,4,6,8]
// 向量比较
const mask = v1 > @splat(2.0); // [0,0,1,1]
// 向量→数组
const arr: [4]f32 = sum;
std.debug.print("sum = {d:.1}\n", .{arr});
// 数组→向量
const from_arr: @Vector(4, f32) = .{ 1.0, 2.0, 3.0, 4.0 };
_ = product; _ = scaled; _ = mask; _ = from_arr;
}
Zig的@typeInfo提供了完整的编译期类型反射:
const std = @import("std");
pub fn main() !void {
// 获取类型信息
const info = @typeInfo(i32);
switch (info) {
.Int => |int_info| {
std.debug.print("i32: signed={}, bits={}\n", .{
int_info.signedness == .signed,
int_info.bits,
});
},
else => unreachable,
}
// 获取类型大小
std.debug.print("i32大小: {}字节\n", .{@sizeOf(i32)});
std.debug.print("f64大小: {}字节\n", .{@sizeOf(f64)});
std.debug.print("bool大小: {}字节\n", .{@sizeOf(bool)});
// 类型对齐
std.debug.print("u64对齐: {}\n", .{@alignOf(u64)});
// 类型名