Zig Note - 01
Zig Note - 01
定义type
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// enum
pub const Mapping = enum {
lorom,
hirom,
exhirom,
unknown,
};
// struct
pub const RomHeader = struct {
title: [21]u8,
map_mode: u8,
cartridge_type: u8,
rom_size_code: u8,
ram_size_code: u8,
region_code: u8,
developer_id: u8,
version: u8,
checksum_complement: u16,
checksum: u16,
reset_vector: u16,
};
// custom error type
const RomError = error{
HeaderOutOfBounds,
InvalidValues,
ChecksumMismatch,
};
闭包
1
2
3
4
5
for (title) |c| {
if (c < 0x20 or c > 0x7d) {
return error.InvalidValues;
}
}
函数返回可能的Error & 处理
返回值类型前加 ! 表示可能返回Error
1
2
3
4
// This function may return Error
fn parse_internal_header(data: []const u8, header_offset: u32) !RomHeader {
...
}
调用函数的时候,可以用下列方式捕获:
1
2
3
4
5
6
if(parse_internal_header(data, offset)) |parsed_header| {
... // success
}
else |err| {
... // error
}
也可以使用catch关键词,只有当前面的结果出现了error后,才会向后执行. 利用该关键字可以将下列逻辑:
1
2
3
4
5
6
7
8
9
10
11
var parsed_header: RomHeader = undefined;
if (parse_internal_header(data, rom_start + 0x7fc0)) |header| {
parsed_header = header;
} else if (parse_internal_header(data, rom_start + 0xffc0)) |header| {
parsed_header = header;
} else if (parse_internal_header(data, rom_start + 0x40FFC0)) |header| {
parsed_header = header;
} else {
... // all failed
}
简化成:
1
const parsed_header =
zig block
如果被包进了{}中,就要在后面加分号。但是下面的语句会创建两个变量,并没有赋给rom_data
1
2
3
4
5
6
7
8
9
10
const rom_data: []const u8 =
if (data_length % 1024 == 512){
data[512..];
}
else if (data_length % 1024 == 0){
data[0..];
}
else {
return error.InvalidValue; // Error
};
正确写法:
1
2
3
4
5
6
7
8
const rom_data: []const u8 =
if (data_length % 1024 == 512)
data[512..]
else if (data_length % 1024 == 0)
data[0..]
else {
return error.InvalidValue; // Error
};
comptime_int
1
2
const size = 1 << 10; // 合法
const size2 = 1 << header.rom_size_code; // 非法
单独写一个1时,属于zig中的comptime_int,它没有固定的位数,可以任意增长. 第一个例子中,因为二者都是固定的数值,所以可以在编译期间确定;但是后一个例子却不行.
解决方法是使用固定长度的1:
1
const size = @as(usize, 1) << @intCast(header.rom_size_code);
explict type
尽管 .{}能够推断类型,但是建立在周围的环境提供了确定类型的前提下。不要以为可以通过{}内的字段来推断!
比如下面的rom_info没有写具体类型,会报错:error: expected type 'src.parser.parser.RomHeader', found 'src.parser.parser.parse_internal_header__struct_43088
1
2
3
4
5
6
7
8
9
fn parse_internal_header(data: []const u8, header_offset: u32) !RomInfo {
......
const rom_info = .{
......
};
return rom_info;
}
加上具体类型后解决.
1
2
3
4
5
6
7
8
9
fn parse_internal_header(data: []const u8, header_offset: u32) !RomInfo {
......
const rom_info: RomInfo = .{
......
};
return rom_info;
}
This post is licensed under CC BY 4.0 by the author.