I just don't think having 'gotcha' rules the compiler exploits to do whatever it wants regardless of programmer intent is a good idea, and that's how C/C++ treats UB. UB should be a compiler error and force the programmer to specify what they want the result to actually be so there are no assumptions on the programmer end and no surprises from the compiler.
> UB should be a compiler error and force the programmer to specify what they want the result to actually be so there are no assumptions on the programmer end and no surprises from the compiler.
Many types of UB are not easily detected at compile time, or cannot be detected in advance at all. For instance, prompting the user for an integer and incrementing it by 1 is UB when the user enters the maximum value of an integer. So should the compiler forbid adding two numbers unless you explicitly guard against overflow? Perhaps it should, but the resulting language definitely wouldn't look anything like C.
Besides, it's not that the compiler is going out of its way to screw you over with a 'gotcha' rule, it's just optimizing using the assumption that your program is free of UB. As a programmer it is your responsibility that there is no UB. If you feel there are too many pitfalls you could use a different programming language, lobby the standards organization for a standard that has less UB, or use compiler options to detect it (e.g. ubsan for clang).
That's a fair point, but it still feels wrong to me that the compiler can throw away large chunks of code and change the outcome of the function silently.
I think the real problem here is that people underestimate the complexity of C and C++. It often feels like it would be easy to guess what the assembly would look like for some snippet of C/C++ code (especially when it's not using any C++ features, such as the loop in the article) when we really should be thinking in terms of the abstract machine that the standard defines.