一段代码演示初学者容易掉坑的“comptime 副作用陷阱”

先看这段代码:

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
}
相关推荐
卷无止境4 分钟前
LangExtract:让LLM从杂乱文本中"抠"出结构化数据的开源工具
后端·python
卷无止境15 分钟前
软件复杂度:那些让代码变得难以理解的东西,到底能不能量化?
后端·python
mldong10 小时前
从 mldong 到 jeeflow:一个工作流引擎的独立进化
后端
陈随易11 小时前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
Aaron - Wistron11 小时前
Web API C# (Furion版)带 单元测试
开发语言·后端·c#
卷无止境11 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境11 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
IT_陈寒13 小时前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端
SomeB1oody14 小时前
【RustyML入门】1.0. 快速上手
开发语言·后端·机器学习·rust·教程