You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Zig实现两数之和报错expected type 'i32', found 'usize' 如何解决?

问题分析与修复方案

错误根源

你看到的错误提示表面上是索引类型不匹配,但实际存在三个核心问题:

  1. try的非法使用:two_sum函数返回类型是[]i32,但map.put可能返回错误(如内存分配失败),try要求函数返回错误联合类型(!T),因此此处的try会触发编译错误。
  2. 索引类型误解:Zig中数组索引必须是usize类型,整数字面量1会自动推断为usize,所以res[1]本身是合法的——你尝试res[@as(i32, 1)]反而错误,因为强制将索引转为i32违反了Zig的索引规则。
  3. 悬垂指针风险:返回栈上局部数组res的指针&res会导致悬垂指针:函数执行完毕后,栈上的res会被销毁,返回的指针指向无效内存,属于未定义行为。
  4. 版本兼容的类型转换:Zig 0.10+版本中,usize转i32需要显式使用@intCast,直接@as(i32, i)会因为类型位数不匹配报错。

修复后的完整代码

const std = @import("std");
const allocator = std.heap.page_allocator;

// 修改返回类型为错误联合类型,适配内存分配的错误可能
fn two_sum(nums: []i32, target: i32) ![]i32 {
    var map = std.AutoArrayHashMap(i32, i32).init(allocator);
    defer map.deinit();

    // 用分配器在堆上创建结果数组,避免悬垂指针
    var res = try allocator.alloc(i32, 2);
    res[0] = -1;
    res[1] = -1;

    for (nums, 0..) |n, i| {
        const complement = target - n;
        if (map.get(complement)) |prev_index| {
            res[0] = prev_index;
            // 显式完成usize到i32的类型转换
            res[1] = @intCast(i32, i);
            return res;
        }
        // 存储当前数字与对应索引(转换为i32)
        try map.put(n, @intCast(i32, i));
    }
    return res;
}

pub fn main() !void {
    var arr = [_]i32{1, 5, 8, 9, 6};
    var x = try two_sum(&arr, 9);
    // 确保堆内存被释放
    defer allocator.free(x);

    for (x) |n| {
        std.debug.print("{d} ", .{n});
    }
    std.debug.print("\n", .{});
}

关键修复点说明

  • 错误处理适配:将two_sum返回类型改为![]i32,允许函数返回错误;main中调用时用try处理错误。
  • 内存安全优化:用allocator.alloc在堆上分配结果数组,搭配defer allocator.free(x)确保内存被正确释放,避免悬垂指针。
  • 合法类型转换:用@intCast(i32, i)完成usize索引到i32的显式转换,符合Zig的类型安全要求。
  • 索引写法修正:保留res[1]的写法,整数字面量1会自动推断为usize,完全符合数组索引的类型规则。

内容的提问来源于stack exchange,提问作者ZeroTerabytes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 02:47:00