← 返回学习

为什么有了 C++、D 和 Rust 还要用 Zig?

没有隐藏的控制流

如果 Zig 代码看起来不像是在跳转调用函数,那么它就不是。这意味着您可以确信以下代码只调用 foo(),然后调用 bar(),并且这种保证无需知道任何类型。

var a = b + c.d;
foo();
bar();

隐藏控制流的示例

此设计决策的目的是提高可读性。

没有隐藏的内存分配

Zig 在堆内存分配方面采取了放任不管的态度。没有 new 关键字或任何其他使用堆分配器的语言特性(例如字符串连接运算符[1])。堆的整个概念由库和应用程序代码管理,而不是由语言本身管理。

隐藏内存分配的示例

几乎所有带有垃圾回收器的语言都散布着隐藏的内存分配,因为垃圾回收器在清理时隐藏了证据。

隐藏内存分配的主要问题在于它阻碍了代码的可重用性,不必要地限制了代码可以部署到的环境数量。简而言之,在某些用例中,人们必须能够依赖控制流和函数调用不会产生内存分配的副作用,因此,一种编程语言只有在能够真实提供这种保证的情况下才能满足这些用例。

在 Zig 中,有提供和使用堆分配器的标准库特性,但这些都是可选的标准库特性,而不是语言本身内置的。如果您从不初始化堆分配器,您可以确信您的程序不会进行堆分配。

每个需要分配堆内存的标准库特性都接受一个 Allocator 参数来完成此操作。这意味着 Zig 标准库支持独立目标。例如,std.ArrayListstd.AutoHashMap 可以用于裸机编程!

自定义分配器使手动内存管理变得轻而易举。Zig 有一个调试分配器,可以在使用已释放内存和重复释放内存的情况下维护内存安全。它会自动检测并打印内存泄漏的堆栈跟踪。还有一个竞技场分配器,您可以将任意数量的分配捆绑在一起并一次性全部释放,而不是独立管理每个分配。专用分配器可用于根据任何特定应用程序的需求提高性能或内存使用率。

[1]: 实际上有一个字符串连接运算符(通常是数组连接运算符),但它只在编译时工作,因此仍然不会进行任何运行时堆分配。

对无标准库的一流支持

如上所述,Zig 有一个完全可选的标准库。每个标准库 API 只有在您使用它时才会被编译到您的程序中。Zig 对链接或不链接 libc 都提供同等支持。Zig 对裸机和高性能开发非常友好。

这兼具两者的优点;例如在 Zig 中,WebAssembly 程序既可以使用标准库的常规特性,与支持编译到 WebAssembly 的其他编程语言相比,仍能生成最小的二进制文件。

一种用于库的可移植语言

编程领域的圣杯之一是代码复用。遗憾的是,在实践中,我们常常发现自己一遍又一遍地重复造轮子。通常这是有道理的。

现有项目的包管理器和构建系统

Zig 除了是一种编程语言外,还是一个工具链。它带有一个 构建系统和包管理器,即使在传统的 C/C++ 项目中也很有用。

您不仅可以用 Zig 代码代替 C 或 C++ 代码,还可以将 Zig 用作 autotools、cmake、make、scons、ninja 等的替代品。最重要的是,它还为原生依赖项提供了包管理器。即使项目的所有代码都是 C 或 C++,这个构建系统也适用。例如,通过将 ffmpeg 移植到 zig 构建系统,只需下载 50 MiB 的 zig,就可以在任何受支持的系统上为任何受支持的系统编译 ffmpeg。对于开源项目,这种简化的从源代码构建(甚至交叉编译)的能力,可能是获得或失去宝贵贡献者的关键。

apt-get、pacman、homebrew 等系统包管理器对于最终用户体验至关重要,但它们可能无法满足开发人员的需求。特定于语言的包管理器可能是项目有无贡献者的关键。对于开源项目,使项目成功构建的难度是潜在贡献者的巨大障碍。对于 C/C++ 项目,拥有依赖项可能是致命的,尤其是在没有包管理器的 Windows 上。即使仅仅构建 Zig 本身,大多数潜在贡献者也会在 LLVM 依赖项上遇到困难。Zig 提供了一种项目直接依赖原生库的方式——无需依赖用户系统包管理器提供正确的版本,并且无论使用何种系统以及针对何种平台,实际上都能保证项目首次构建成功。

其他语言也有包管理器,但它们不像 Zig 那样能消除烦人的系统依赖。

Zig 可以用一种合理的语言和声明式 API 来替代项目的构建系统,该 API 也提供了包管理,从而能够真正依赖其他 C 库。拥有依赖项的能力实现了更高层次的抽象,从而促进了可重用高级代码的普及。

简洁性

C++、Rust 和 D 具有如此多的特性,以至于它们可能会分散您对所开发应用程序实际意义的注意力。人们会发现自己在调试对编程语言的了解,而不是调试应用程序本身。

Zig 没有宏,但仍然足够强大,能够以清晰、不重复的方式表达复杂的程序。即使是 Rust 也有像 format! 这样的特殊宏,它是在编译器本身中实现的。而在 Zig 中,等效函数是在标准库中实现的,编译器中没有特殊情况代码。

工具链

Zig 可以从下载页面获取。Zig 提供适用于 Linux、Windows 和 macOS 的二进制归档文件。以下描述了您通过这些归档文件获得的内容