先看这段代码:
c
const std = @import("std");
const print = std.debug.print;
pub fn main() !void {
var data: i32 = 99;
const T = @TypeOf(foo(i32, &data));
print("type: {}\n", .{T});
print("data = {d}\n", .{data});
}
fn foo(T: type, ptr: *T) T {
ptr.* += 1;
return ptr.*;
}
这段 Zig 程序看起来会调用 foo(),修改了 data,然后打印出来,但实际运行时你会发现:
ini
type: i32
data = 99
data 根本没有变成 100!这让人非常困惑:明明写了 foo(i32, &data),为什么 ptr.* += 1 没有生效?
根本原因:foo 被当做了 comptime 函数调用! 关键代码在这里:
zig
const T = @TypeOf(foo(i32, &data));
@TypeOf(...) 是一个 编译期内置函数,它只关心表达式的类型,不关心运行时的副作用。
Zig 的规则是:
只要一个表达式的结果在编译期是已知的,编译器就有权在编译期就把整个表达式求值完成(包括函数调用),即使这个函数有副作用。
Zig通过对等类型解析,在编译期完成了类型的推导。
如何让它真正修改运行时的 data?
要避免在编译期求值这个调用:
zig
pub fn main() !void {
var data: i32 = 99;
// 方案1:先调用,再取类型(推荐)
const result = foo(i32, &data); // 运行时调用
const T = @TypeOf(result); // 现在才 comptime 求类型
print("type: {}\n", .{T});
print("data = {d}\n", .{data}); // → 100
}