Zig实现两数之和报错expected type 'i32', found 'usize' 如何解决?
问题分析与修复方案
错误根源
你看到的错误提示表面上是索引类型不匹配,但实际存在三个核心问题:
try的非法使用:two_sum函数返回类型是[]i32,但map.put可能返回错误(如内存分配失败),try要求函数返回错误联合类型(!T),因此此处的try会触发编译错误。- 索引类型误解:Zig中数组索引必须是
usize类型,整数字面量1会自动推断为usize,所以res[1]本身是合法的——你尝试res[@as(i32, 1)]反而错误,因为强制将索引转为i32违反了Zig的索引规则。 - 悬垂指针风险:返回栈上局部数组
res的指针&res会导致悬垂指针:函数执行完毕后,栈上的res会被销毁,返回的指针指向无效内存,属于未定义行为。 - 版本兼容的类型转换: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
相关产品推荐
相关产品推荐

