一段代码演示初学者容易掉坑的“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
}
相关推荐
计算机学姐6 分钟前
基于SpringBoot的高校论坛系统【2026最新】
java·vue.js·spring boot·后端·spring·java-ee·tomcat
Victor3561 小时前
Hibernate(13) Hibernate的一级缓存是什么?
后端
毕设源码-赖学姐1 小时前
【开题答辩全过程】以 基于SpringBoot的健身房管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
Victor3561 小时前
Hibernate(14)什么是Hibernate的二级缓存?
后端
czlczl200209251 小时前
SpringBoot自动配置AutoConfiguration原理与实践
开发语言·spring boot·后端
heartbeat..2 小时前
Servlet 全面解析(JavaWeb 核心)
java·网络·后端·servlet
vx_bisheyuange2 小时前
基于SpringBoot的疗养院管理系统
java·spring boot·后端
京东零售技术2 小时前
2025京东零售技术年度精选 | 技术干货篇(内含福利)
前端·javascript·后端
布列瑟农的星空3 小时前
2025年度总结——认真生活,快乐工作
前端·后端
sunnyday04263 小时前
Spring Boot 项目中使用 Dynamic Datasource 实现多数据源管理
android·spring boot·后端