一段代码演示初学者容易掉坑的“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
}
相关推荐
mCell1 小时前
你以为短链接只是 Hash + 301/302?
后端·算法·架构
咖啡八杯2 小时前
GoF设计模式——迭代器模式
java·后端·设计模式·迭代器模式
IT_陈寒5 小时前
SpringBoot自动配置不是你以为的那样的智能
前端·人工智能·后端
程序员张37 小时前
SpringBoot集成BCrypt密码加密库
java·spring boot·后端
CaffeinePro7 小时前
FastAPI数据库集成SQLAlchemy异步ORM全方案
后端·fastapi
小旭Coding7 小时前
凌晨告警轰炸!Go 服务协程只增不减,内存持续暴涨直至 OOM
后端
半个落月7 小时前
用 LangChain.js 手写一个能读写文件和执行命令的 Mini Cursor
javascript·人工智能·后端
952368 小时前
RabbitMQ-基础操作
java·spring boot·分布式·后端·spring·rabbitmq
柒和远方8 小时前
从审计日志到可下载证据包:事务型 Outbox、租约 fencing 与保留水位
前端·后端·架构
geovindu10 小时前
CSharp: Prototype Pattern
开发语言·后端·设计模式·.net·原型模式·创建型模式