FWIW, Rust can also do a lot of things that do not easily map to C (at least standard C) constructs. For example:
- You can compare any two pointers, while in C they must point to the same allocation. This is possible to solve by converting to integers first.
- Signed integer overflow is UB in C, defined to wrap/panic in Rust.
- Type-based alias analysis is a big one, does not exist in Rust.
> You can compare any two pointers, while in C they must point to the same allocation. This is possible to solve by converting to integers first.
Indeed specifically Rust defines that pointer comparisons are done by address, whereas C doesn't specify what the rules are exactly. This gets sticky if the pointer was invalidated (e.g. you free'd the memory it was pointing at). Rust says - as you might expect - that you can still compare this invalid pointer to another pointer (which may or may not still be valid and indeed might be a valid pointer to the same address!) because we're only comparing the address - but C++ says you mustn't do that and I believe C has the same rule.
> Signed integer overflow is UB in C, defined to wrap/panic in Rust.
This doesn't feel like an interesting difference. C made a weird choice, which was maybe convenient for the usual Worse Is Better reasons 50+ years ago. LLVM doesn't care about that choice, LLVM can cheerfully simulate this behaviour in C if you want that.
> Type-based alias analysis is a big one, does not exist in Rust.
This also doesn't feel relevant but I guess I'm interested in why you think it would make "a big" difference?
Edited: I confirmed C11 has "pointer zap" which is the behaviour I described above, and I believe C23 also still has pointer zap although paulmck and co. are trying to get rid of it or do something on this topic in C2y.