为何系统编程选 Zig 而非 C
Why Zig over C for Systems Programming
C 语言依然是 UNIX 的基石,但我在编写新代码时已转向 Zig。Zig 保留了 C 的简洁与对硬件的直接控制,却解决了 C 最让人头疼的问题:无需 goto 即可优雅处理资源清理,slice 自带长度避免缓冲区溢出,错误处理强制编译器检查,comptime 替代了晦涩的预处理器。更重要的是,Zig 编译器能在 debug 模式下捕获整数溢出等未定义行为。虽然 C 生态更成熟,但 Zig 让系统编程在保持底层控制的同时,显著减少了低级错误。
C 是我最喜欢的编程语言!但我写这篇文章是因为我再也不想用 C 写新代码了。
HN 评论区
192- uecker
Zig 是一门不错的语言,但那些文章总是拿新语言和那种不使用现代工具的旧式 C 做对比。如果你愿意采用现代工具链和编程风格,列表中的大多数优势在 C 中也能实现:有符号溢出检查可以用 sanitizers;无法忽略的错误可以用 [[nodiscard]];知道自身大小的切片类型可以用可变修饰类型(variably-modified types)或 span 类型。
Defer 功能很快也会出现在 C 编译器中,不过就我个人而言,我仍然觉得 goto 错误处理更清晰。
(Rust 在临时内存安全方面确实有优势,但这点并不适用于 Zig。)
- variadix
在使用 C 很长一段时间之后,我最终选择了一种 C++ 方言来进行系统编程。它大部分像 C,我禁用了异常、RTTI 等功能,但我确实使用了模板、重载、方法、lambda 等特性。
我有自己的对象系统,其中的构造函数方法都返回状态码,这样就不需要异常了;我还有自己的标准库,包含容器、缓冲 I/O、网络、哈希、数学运算、线程、异步等功能。
C++ 提供了所有必要的特性,让你能够有效地构建自己的语言,而且由于 C++ 支持广泛,你可以使用一流的工具体系。LLM 也让独自构建和测试整个标准库变得容易得多。
- pron
另外,Zig 的表达力至少和 C++ 一样强(但没有那种隐式性和普遍的语言复杂性,这些特性使得审查某些敏感代码变得困难,因为你需要确切地看到执行了哪些操作),并且它在 arena(内存区)支持方面优于 C/C++/Rust。
- asveikau
仅从第一个例子来看:
struct user *user_new(const char *name, size_t n_groups)
{
struct user *u = malloc(sizeof *u);
if (u == NULL)
goto fail;
u->name = strdup(name);
if (u->name == NULL)
goto fail_user;
u->groups = calloc(n_groups, sizeof *u->groups);
if (u->groups == NULL)
goto fail_name;
return u;
fail_name:
free(u->name);
fail_user:
free(u);
fail:
return NULL;
}
我觉得你可以比这更好地展示 C 的写法。我喜欢专注于一个清理块,并利用 free(NULL) 是空操作这一事实。
struct user *user_new(const char *name, size_t n_groups)
{
struct user *u = calloc(sizeof *u, 1);
if (u == NULL)
goto fail;
u->name = strdup(name);
if (u->name == NULL)
goto fail;
u->groups = calloc(n_groups, sizeof *u->groups);
if (u->groups == NULL)
goto fail;
return u;
fail:
if (u)
{
free(u->name);
free(u->groups);
}
free(u);
return NULL;
}
不过要注意,这假设了 calloc(sizeof *u, 1) 会将指针初始化为 NULL。据我所知,假设 NULL 的位模式全为零在技术上违反了标准,但你可能会针对的每个系统都能正常工作。
如果你遵循“释放 NULL 指针没问题”的模式,你还可以重用 free 函数:[...]
- drnick1
所有这些新语言相对于 C 来说都难以阅读。如果像我一样,你喜欢显式的写法,比如 for (size_t i = 0; i <= n; i++) total += a[i]; 那么所有这些新语言都做不到。
- qweqwe14
Rust 迟早会取代所有这些小众语言。是的,从长远来看,Rust 是 C 和 C++ 的可行替代品。Zig 只是试图做一个中间地带,而我们已经证实这行不通。在 LLM 时代,Zig 相比 Rust 尤其无关紧要。
- kombine
顺便提一下,D 和 Nim 其实几年前就已经拥有这些特性了。
- seanw444
关于我在评论里看到的关于线程的讨论:这真让人沮丧。我们有像 Zig 和 Nim 这样的语言,它们是为了美感和直觉而设计的,但随后却有一堆唱反调的人,只会说“除了 Rust 和 Go 之外的一切语言都因为 LLM 而死了,大势已去,关掉它回家吧”。
这种能力——通过前所未有的大规模抄袭工厂,以极低的脑力消耗,以创纪录的速度吐出半成品且脆弱的代码——已经将钟摆猛烈地推向了智识主义和人类思维的对立面。这就是人们因 AI 而感到抑郁的原因。这是一场通往无灵魂状态的革命。