In Rust, the only way to trigger undefined behavior is the presence of unsafe code. So everything outside of manipulating COUNTER in your code block cannot trigger undefined behavior. In C, there aren't any of those guarantees, so any line in the code could potentially trigger undefined behavior. Since we know that only the block manipulating COUNTER can cause undefined behavior to occur, ensuring that the block manipulating COUNTER can not cause undefined behavior to occur is the only place where heavy scrutiny is needed...as opposed to C, where every function call and line of code would need to be scrutinized.
Sure you could throw unsafe everywhere and not check anything, but that misses a major reason to use rust--safe abstractions over unsafe behavior. Once a safe abstraction exists for unsafe behavior, all the heavy lifting of guaranteeing code will not result in undefined behavior is offloaded to the compiler, instead of the programmer having to keep track of it all.