28、C语言与其他语言的对比:C与Rust、Go、Zig在系统编程领域的比较
系统编程这个领域,C语言已经统治了快五十年。说实话,这个地位挺吓人的。
但最近十年,Rust、Go、Zig这些新语言纷纷冒出来,都号称要「取代C」。我一开始也觉得是噱头,直到自己亲手用它们写了几个项目……嗯,有些地方确实让人眼前一亮。
今天咱们就掰开揉碎,看看C跟这几个后起之秀到底差在哪、好在哪。
一、内存安全:C的阿克琉斯之踵
C语言最大的痛,就是内存安全。我在项目中遇到过无数次段错误,查起来真是要命。你想想看,一个野指针、一次缓冲区溢出,就能让整个系统崩溃。
Rust 在这方面做得最绝。它搞了一套所有权(Ownership)和借用(Borrowing)机制,编译期就把内存问题全堵死了。
// Rust 示例:所有权系统
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 的所有权转移给了 s2
// println!("{}", s1); // 编译错误!s1 已失效
}
我第一次写Rust时,被编译器骂得狗血淋头。但习惯了之后,确实再也没跑出过内存泄漏。代价是什么?学习曲线陡得像悬崖。
Go 选择了另一条路——垃圾回收(GC)。你只管分配内存,Go后台自动帮你回收。简单是简单,但GC带来的停顿,在实时系统里是致命的。
Zig 则更接近C的思路:没有GC,没有所有权,全靠开发者自己管理。但它提供了编译时的安全检查,比如数组越界检查。
我的看法:
如果你写的是航天、医疗设备这类「死都不能出bug」的系统,Rust是更好的选择。但如果你像我一样,经常写嵌入式驱动、操作系统内核,C的灵活性和可控性依然无可替代。
二、并发模型:谁更懂多核?
现在的CPU都是多核的,并发编程成了必修课。C语言在这方面……嗯,基本靠pthreads库,你得自己管锁、管条件变量、管死锁预防。
Go 的goroutine是我用过最爽的并发模型。你写个 go func() 就启动了一个轻量级线程,底层由Go运行时调度。
// Go 示例:goroutine
func main() {
ch := make(chan int)
go func() {
ch <- 42
}()
fmt.Println(<-ch)
}
我有个项目,用C写了个多线程下载器,光锁就调了两天。后来用Go重写,半天搞定。但Go的goroutine有个坑:它默认的栈很小(几KB),但如果你不小心写了死循环,整个程序就卡死了。
Rust 的并发模型更安全。它通过Send和Sync trait,在编译期就防止了数据竞争。代价是写起来比较绕,尤其是生命周期标注,能把人绕晕。
Zig 目前没有内置的并发模型,它更倾向于让你用操作系统原生的线程和原子操作。说白了,Zig觉得「并发是库的事,不是语言的事」。
| 语言 | 并发模型 | 安全性 | 学习成本 |
|---|---|---|---|
| C | pthreads + 手动锁 | 低(容易死锁) | 高 |
| Go | goroutine + channel | 中(GC停顿) | 低 |
| Rust | 所有权 + Send/Sync | 高(编译期检查) | 极高 |
| Zig | 原生线程 + 原子操作 | 中(依赖开发者) | 中 |
三、编译速度与工具链
C语言的编译速度,说实话,挺慢的。尤其是大型项目,make一下能喝杯咖啡。我有个嵌入式项目,全量编译要15分钟。
Go 的编译速度是出了名的快。它没有头文件,没有复杂的模板展开,编译一个中型项目也就几秒钟。
Rust 的编译速度……嗯,是它的短板。因为要做大量的静态分析和泛型单态化,编译时间经常以分钟计。我有个Rust项目,改一行代码,重新编译要等40秒。
Zig 在这方面做得不错。它直接调用系统自带的C编译器(如clang),而且没有隐式的依赖分析,编译速度比C还快一点。
小技巧:
如果你在C项目里用CMake,可以试试Zig的build系统。它能直接编译C代码,而且速度更快。我最近就在这么干,效果不错。
四、与C的互操作性
这一点很关键。系统编程不是从零开始,你得跟现有的C库、C代码打交道。
Rust 提供了FFI(外部函数接口),可以直接调用C函数。但有个问题:Rust的字符串不是以'\0'结尾的,传参时得手动转换。
// Rust 调用 C 的 printf
extern "C" {
fn printf(format: *const u8, ...) -> i32;
}
fn main() {
let msg = b"Hello from Rust\0";
unsafe {
printf(msg.as_ptr());
}
}
Go 的cgo机制也能调用C代码,但性能开销比较大。每次cgo调用都要切换栈,频繁调用时性能下降明显。
Zig 在这方面做得最自然。它可以直接编译C代码,甚至能直接使用C的头文件。我试过把一段C代码直接粘贴到Zig文件里,稍微改改就能跑。
注意:
Zig虽然能直接编译C代码,但C的宏定义、条件编译这些特性,在Zig里需要手动处理。我曾经被一个复杂的宏定义坑了半天,最后还是老老实实手动翻译了。
五、知识体系对比图
下面这张图,是我根据多年经验总结的。它展示了C、Rust、Go、Zig在系统编程核心维度上的定位。
从图上可以看得很清楚:C和Zig在「高性能、低安全」这个象限,Rust在「高性能、高安全」,Go在「低性能、高安全」。没有完美的语言,只有适合的场景。
六、我的选择建议
说了这么多,到底该用哪个?我个人的经验是这样的:
- 写操作系统内核、嵌入式驱动:首选C。Zig可以作为备选,但生态还不够成熟。
- 写网络服务、CLI工具:Go是最舒服的。开发效率高,部署简单。
- 写安全敏感的系统组件:比如浏览器引擎、加密库,Rust是更好的选择。
- 写性能极致、又不想放弃安全:可以试试Zig。它比C安全,又比Rust简单。
最后说一句:
语言只是工具。我见过用C写出优雅代码的人,也见过用Rust写出屎山的人。关键还是看你对底层原理的理解,以及……嗯,写代码的习惯。