变量与常量 #

一、变量声明 #

1.1 var 关键字 #

使用 var 声明可变变量:

zig
const std = @import("std");

pub fn main() void {
    var count: i32 = 0;
    count = 10;
    count += 5;
    
    std.debug.print("count = {}\n", .{count});
}

1.2 const 关键字 #

使用 const 声明常量:

zig
const std = @import("std");

pub fn main() void {
    const pi: f64 = 3.14159;
    const name = "Zig";
    
    std.debug.print("pi = {d}\n", .{pi});
    std.debug.print("name = {s}\n", .{name});
}

1.3 类型推断 #

Zig 可以自动推断类型:

zig
const std = @import("std");

pub fn main() void {
    const inferred_int = 42;        // 推断为 comptime_int
    const inferred_float = 3.14;    // 推断为 comptime_float
    const inferred_string = "hello"; // 推断为 *const [5:0]u8
    
    std.debug.print("{}\n", .{@TypeOf(inferred_int)});
    std.debug.print("{}\n", .{@TypeOf(inferred_float)});
    std.debug.print("{}\n", .{@TypeOf(inferred_string)});
}

二、const vs var #

2.1 常量(const) #

zig
const std = @import("std");

pub fn main() void {
    const x: i32 = 10;
    // x = 20;  // 编译错误:不能修改常量
    
    // 但如果 const 是指针,可以修改指向的值
    var value: i32 = 10;
    const ptr: *i32 = &value;
    ptr.* = 20;  // 这是允许的
    
    std.debug.print("value = {}\n", .{value});
}

2.2 变量(var) #

zig
const std = @import("std");

pub fn main() void {
    var x: i32 = 10;
    x = 20;  // 允许修改
    
    // var 必须被使用,否则会警告
    var y: i32 = 30;
    std.debug.print("x = {}, y = {}\n", .{ x, y });
}

2.3 选择原则 #

场景 使用
值不会改变 const
值需要改变 var
编译时已知 constcomptime
运行时确定 varconst

三、const 的特殊行为 #

3.1 const 指针 #

zig
const std = @import("std");

pub fn main() void {
    var value: i32 = 10;
    
    // const 指针,可以修改指向的值
    const ptr: *i32 = &value;
    ptr.* = 20;
    
    // const 常量指针,不能修改指针本身
    const ptr2: *const i32 = &value;
    // ptr2.* = 30;  // 错误:不能修改 const 指向的值
    
    std.debug.print("value = {}\n", .{value});
}

3.2 const 切片 #

zig
const std = @import("std");

pub fn main() void {
    var arr = [_]i32{ 1, 2, 3, 4, 5 };
    
    // const 切片,可以修改元素
    const slice: []i32 = arr[0..];
    slice[0] = 100;
    
    // const 切片指向 const 数据
    const const_slice: []const i32 = arr[0..];
    // const_slice[0] = 200;  // 错误
    
    std.debug.print("arr[0] = {}\n", .{arr[0]});
}

四、comptime #

4.1 编译时计算 #

comptime 关键字强制在编译时执行:

zig
const std = @import("std");

pub fn main() void {
    comptime {
        const x = 10;
        const y = 20;
        std.debug.print("Compile time: {}\n", .{x + y});
    }
}

4.2 comptime 参数 #

函数参数可以是编译时已知的:

zig
const std = @import("std");

fn fibonacci(comptime n: u32) u32 {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

pub fn main() void {
    const result = comptime fibonacci(10);
    std.debug.print("fibonacci(10) = {}\n", .{result});
}

4.3 comptime 类型 #

zig
const std = @import("std");

fn printType(comptime T: type) void {
    std.debug.print("Type: {}\n", .{T});
}

pub fn main() void {
    printType(i32);
    printType(f64);
    printType([]const u8);
}

4.4 comptime 变量 #

zig
const std = @import("std");

pub fn main() void {
    comptime var i: usize = 0;
    inline while (i < 5) : (i += 1) {
        std.debug.print("{}\n", .{i});
    }
}

五、变量初始化 #

5.1 显式初始化 #

zig
const std = @import("std");

pub fn main() void {
    var x: i32 = 10;
    var y: f64 = 3.14;
    var name: []const u8 = "Zig";
    
    std.debug.print("x = {}, y = {d}, name = {s}\n", .{ x, y, name });
}

5.2 未定义值 #

使用 undefined 表示未初始化:

zig
const std = @import("std");

pub fn main() void {
    var x: i32 = undefined;
    x = 10;  // 必须在使用前赋值
    
    std.debug.print("x = {}\n", .{x});
}

5.3 默认值 #

zig
const std = @import("std");

const Point = struct {
    x: i32 = 0,
    y: i32 = 0,
};

pub fn main() void {
    const p1 = Point{};
    const p2 = Point{ .x = 10 };
    const p3 = Point{ .x = 10, .y = 20 };
    
    std.debug.print("p1: ({}, {})\n", .{ p1.x, p1.y });
    std.debug.print("p2: ({}, {})\n", .{ p2.x, p2.y });
    std.debug.print("p3: ({}, {})\n", .{ p3.x, p3.y });
}

六、作用域 #

6.1 块作用域 #

zig
const std = @import("std");

pub fn main() void {
    const x = 10;
    
    {
        const x = 20;  // 遮蔽外层 x
        std.debug.print("Inner x = {}\n", .{x});
    }
    
    std.debug.print("Outer x = {}\n", .{x});
}

6.2 文件作用域 #

zig
const std = @import("std");

const file_constant = 100;  // 文件级别常量

pub fn main() void {
    std.debug.print("file_constant = {}\n", .{file_constant});
}

6.3 全局变量 #

zig
const std = @import("std");

var global_counter: i32 = 0;

fn increment() void {
    global_counter += 1;
}

pub fn main() void {
    increment();
    increment();
    increment();
    std.debug.print("global_counter = {}\n", .{global_counter});
}

七、类型转换 #

7.1 显式转换 #

zig
const std = @import("std");

pub fn main() void {
    const a: i32 = 100;
    const b: f32 = @floatFromInt(a);
    const c: u8 = @intCast(a);
    
    std.debug.print("a = {}, b = {d}, c = {}\n", .{ a, b, c });
}

7.2 常用转换函数 #

函数 说明
@intCast 整数类型转换
@floatCast 浮点类型转换
@floatFromInt 整数转浮点
@intFromFloat 浮点转整数
@intFromBool 布尔转整数
@intFromPtr 指针转整数
@ptrFromInt 整数转指针
@truncate 截断整数
@as 通用类型转换

7.3 @as 用法 #

zig
const std = @import("std");

pub fn main() void {
    const x = @as(i32, 10);
    const y = @as(f64, 3.14);
    const z = @as(u8, 255);
    
    std.debug.print("x = {}, y = {d}, z = {}\n", .{ x, y, z });
}

八、常量表达式 #

8.1 编译时常量 #

zig
const std = @import("std");

const SIZE: usize = 100;
const BUFFER_SIZE = SIZE * 2;

pub fn main() void {
    var buffer: [BUFFER_SIZE]u8 = undefined;
    std.debug.print("Buffer size = {}\n", .{buffer.len});
}

8.2 运行时常量 #

zig
const std = @import("std");

pub fn main() void {
    const input = try std.io.getStdIn().reader().readByte();
    const doubled = input * 2;  // 运行时计算
    std.debug.print("doubled = {}\n", .{doubled});
}

九、最佳实践 #

9.1 优先使用 const #

zig
// 好
const max_size = 100;
const default_name = "unknown";

// 避免
var max_size = 100;  // 不需要修改
var default_name = "unknown";

9.2 避免变量遮蔽 #

zig
// 不推荐
const x = 10;
const x = 20;  // 遮蔽

// 推荐
const x = 10;
const y = 20;

9.3 使用有意义的名称 #

zig
// 好
const max_connections = 100;
const user_name = "Alice";
var item_count: usize = 0;

// 不好
const mc = 100;
const n = "Alice";
var cnt: usize = 0;

十、总结 #

变量与常量要点:

概念 说明
const 不可变绑定
var 可变变量
comptime 编译时执行
undefined 未定义值
类型推断 自动推断类型

下一步,让我们学习 Zig 的基本数据类型!

最后更新:2026-03-27