C vs. Rust: Variable Declaration
Rust and C differ in many ways. In terms of variable declaration, Rust is “safer”. In C you can declare a variable without initializing it, and the compiler does not check whether it has been initialized; Rust, however, performs strict checks and will report a compile error if a declared variable is uninitialized. This prevents bugs caused by uninitialized variables.
In C you can declare a variable and use it without initialization; the compiler won’t complain, but it may lead to abnormal runtime behavior. For example:
#include<stdio.h>
#include <stdbool.h>
bool is_post(int data) {
return data > 0;
}
int main() {
bool var;
/* assume a lot of code in between */
int data = 10;
if (data != 10)
{
var = is_post(data);
}
/* assume a lot of code in between */
// the variable might end up used without ever being initialized
if (var)
printf("maybe error here.\n");
else
printf("maybe not you want.\n");
return 0;
}
If you don’t initialize at declaration, you must ensure it is assigned before use; otherwise it may cause incorrect results or other strange problems. When the project is large, such bugs are hard to track down.
For Rust, a variable must be initialized at declaration, otherwise it won’t even pass the compiler, so you won’t fall into this pit.
fn main() {
let a;
if a > 1 {
a = 10;
}
}
Compiling with cargo build:
error[E0381]: use of possibly-uninitialized variable: `a`
--> src/main.rs:4:8
|
4 | if a > 1 {
| ^ use of possibly-uninitialized `a`
For more information about this error, try `rustc --explain E0381`.
error: could not compile `playground` due to previous error
Mutability
In Rust variables are immutable by default, e.g. let a = 10. To declare a mutable variable you must add mut, e.g. let mut a = 10. In C it’s the opposite: you can freely modify a variable unless you declare it const as a constant. When talking about Rust, the word “safe” comes up. Rust emphasizes not only memory safety but also reflects this design philosophy in other aspects. Default immutability, regardless of its original motivation, is indeed less error-prone in practice. If immutable by default, any attempt to modify is caught at compile time, avoiding the easy mistakes made when variables are mutable by default. For example, when writing C functions we often develop the habit:
int func(const char *name, const int value)
{
......
}
The benefit is twofold: on one hand it prevents accidental modification of parameters inside the function, catching errors at compile time; on the other hand it helps readers of the code immediately know the parameter won’t be modified inside the function. This is undoubtedly a good programming habit. In Rust, immutability by default and mut only when mutable brings similar benefits: it avoids accidental modification of immutable variables, and makes the code easier to understand when reading others’ large codebases. It has a flavor of best engineering practice. When the codebase is large, logic errors are easy to locate, but bugs often stem from such inconspicuous small details, which are harder to pinpoint.