If n!=0 return 1/n
Is well behaved: Division by zero wont happen. z=1/n
If n!=0 return z
Is not well behaved. It will crash when n=0. What the compiler does is take the existence of z as a proof that n can't be 0, and optimize the if away: z=1/n
return z
Just like division by 0, undefined behaviour (UB) is not allowed. The difference is: UB might crash or give a nonsensical result. You can't tell beforehand. Different versions of a compiler might make different choices of crash vs nonsense. Until recently, the author calculated nonsense, and threw it away, but that was accidental. It might have crashed too.C had a lot of UB that gets thrown away, until some minor shift in optimizations changes it to a crasher. Compare it to an insanely sharp knife: Powerfull, but the slightest error might take off your fingers, it's very hard to know if something is or is not an error, and errors mostly dont cut if your fingers, until surprise surprise they do.
Rust is much better: only unsafe code behaves like C's crazy knife. Only when you use unsafe, the rust guarantees go out of the window, because that's what the programmer explicitly asked.