Another thing just to mention here is `strip`, which IIRC `cargo build --release` doesn't do by default. I think `stripping` binaries can reduce binary size by up to 80-85% in some cases (but certainly not all; just tried it locally on a 1M rust binary and got 40% reduction).
You can strip C compiled binaries too. And that halves the binary size. The point is for example a hello world Rust binaries is 300kb after striping while C compiled one is 15kb. A difference of 20 times.
Such comparison exaggerates the difference, because it’s a one-time constant overhead, not a multiplicative overhead.
i.e. all programs are larger by 275KB, not larger by 20x.
Rust doesn’t have the privilege of having a system-wide shared stdlib to make hello world executables equally small.
The overhead comes from Rust having more complex type-safe printf, and error handling code for when the print fails. C doesn’t handle the print error, and C doesn’t print stack traces on error. Most of that 200KB Rust overhead is a parser for dwarf debug info to print the stack trace.
That might be true for Hello World, but libgcc_s is where a lot of builtins for C itself go, so you'll find it ends up linked into a lot of non-trivial C programs as well. See https://gcc.gnu.org/onlinedocs/gccint/Libgcc.html
That's not why rust statically links the runtime. The main benefit is that they don't have to try to design and maintain a stable ABI for it. Which is not moot.
More generally, you statically link something to avoid distribution hassles of various kinds, not because you care about the specific number.
FWIW, you can configure this in Cargo.toml:
[profile.release] strip = true