@@ -4,19 +4,23 @@ outline: deep
44
55# 可选类型
66
7- zig 在不损害效率和可读性的前提下提高代码安全性的一个方案就是可选类型,` ? ` 是可选类型的标志,你可以将它放在类型的前面,代表它的值是 null 或者这个类型。
7+ ## Overview
8+
9+ 在 Zig 中,要在不损害效率的前提下,尽量提高代码安全性,其中一个方案就是可选类型,他的标志是 ` ? ` ,` ?T ` 表示它的值是它的值是 ` null ` 或` T ` 。
810
911<<<@/code/release/optional_type.zig#basic_type
1012
11- 当然,可选类型在整数上没什么大用,更多是在指针上使用,null(空引用)是许多运行时异常的根源,甚至被指责为[ 计算机科学中最严重的错误] ( https://www.lucidchart.com/techblog/2015/08/31/the-worst-mistake-of-computer-science/ ) 。
13+ 当然,它一般在指针上发挥作用,而不是整数。
14+
15+ ` null ` (空引用)是许多运行时异常的根源,甚至被指责为[ 计算机科学中最严重的错误] ( https://www.lucidchart.com/techblog/2015/08/31/the-worst-mistake-of-computer-science/ ) 。
1216
13- 当然这在 zig 中不存在,通过可选类型我们可以解决这个问题, zig 在解决空指针上采取的方式比较保守,它兼顾了代码的可读性和效率问题 。
17+ 我们可以通过可选类型来规避它。这其实是一种比较保守的做法,它同时兼顾了代码的可读性和运行效率。目前最为激进的应该是 _ Rust _ ,它真的是非常的激进,这增加了程序员在写代码时的心智负担(因为你经常需要和编译期斗智斗勇,但好处大大是减少了你在运行时 _ Debug _ 的负担)。相对地, zig 采取了一种折中方案,编译期进行简单的检测,而且检测出来的错误一般很容易纠正;这样的缺点是并不能保证你的运行时是绝对安全的(可选类型仅仅能避免空指针问题,却不能避免悬空指针、迷途指针和野指针等问题) 。
1418
15- 其中目前最为激进的应该是 _ Rust _ ,它真的是非常的激进,这增加了程序员在写代码时的心智负担(因为你经常需要和编译期斗智斗勇,但好处大大是减少了你在运行时 _ Debug _ 的负担)。相对来说,zig 采取的是一种折中的方案,编译期仍然会给你检测,并且这种检测不是很深奥,而且纠正起来很简单,缺点是并不能保证你的运行时是绝对安全的(可选类型仅仅能保证你不使用空指针,却不能保证你出现悬空指针【迷途指针、野指针】等情况的出现) 。
19+ zig 将 ` null ` 特殊看待,并且保证 ` null ` 不会被赋值给一个非可选类型变量 。
1620
17- zig 会将 ` null ` 特殊看待,并且保证你不会将一个可能为 ` null ` 的值赋值给一个不可能是 ` null ` 的变量。
21+ ## 和 C 对比
1822
19- 首先我们和 zig 的目标:C 对比一下,看一下两者在处理 ` null ` 上的区别,在接下来的代码中,我们尝试调用 ` malloc ` ,并且申请一块内存:
23+ 看看下面代码中两者在处理 ` null ` 上的区别。(尝试调用 ` malloc ` 申请一块内存。)
2024
2125::: code-group
2226
@@ -35,9 +39,9 @@ struct Foo *do_a_thing(void) {
3539
3640:::
3741
38- 在这里,至少 zig 看起来要比 c 好用, 我们通过使用 `orelse` 关键字保证解构了可选类型,保证我们这里的 `ptr` 一定是一个可用的指针,否则的话我们直接会返回 `null`。
42+ 在这里,我们通过使用 `orelse` 解构了可选类型,保证 `ptr` 是一个合法可用的指针,否则直接返回 `null`。(这看起来比 C 更加明了且易用)
3943
40- 我们再来对比一下 _C_ 和 _Zig_ 处理 `null` 的方式 :
44+ 再看下例 :
4145
4246:::code-group
4347
@@ -55,9 +59,9 @@ void do_a_thing(struct Foo *foo) {
5559
5660:::
5761
58- 看起来区别不大,zig 只是在 if 语法有点不同,这个块中保证了 ` foo ` 不是一个可选类型的指针,而是一个指针 。
62+ 看起来区别不大,只是在 ` if ` 语法上有点不同, ` if ` 块中保证 ` foo ` 不为 ` null ` 。
5963
60- 当然在 c 中你可以使用 ` __attribute__((nonnull)) ` 来告诉 GCC 编译器这里不能是一个 null,但使用成本明显要比 zig 高。
64+ 当然,在 C 中,你可以用 ` __attribute__((nonnull)) ` 来告诉 C 编译器这里不不可能是 ` null ` ,但其使用成本明显比 Zig 高。
6165
6266## 编译期反射访问可选类型
6367
@@ -68,10 +72,6 @@ void do_a_thing(struct Foo *foo) {
6872
6973<<<@/code/release/optional_type.zig#comptime_access_optional_type
7074
71- ## ` null `
72-
73- ` null ` 是一个独特的类型,类似 ` undefined ` ,它的使用方式就是赋值给可选类型!
74-
7575## 可选指针
7676
7777可选指针会保证和指针有一样的大小,` null ` 会被视作地址 0 考虑!
0 commit comments