If this seems unintuitive, consider a more general example:
int foo(int x) { if (x >= 0) return 123; if (x < 0) return 456; }
What’s the “expected” return value if neither of the if-statements match? That seems like a nonsensical question because the conditions are clearly mutually exclusive, but if you’re a dumb enough compiler (or the conditions are more complex) you might not be able to prove that. So should it return zero? Should the compiler insert code to save and remember the result of the last function call? According to the C standard, the compiler doesn’t have to handle this situation; it is free to assume that the branches are indeed mutually exclusive, and it will most likely do whatever produces the easiest/fastest code in that case.
In the OP’s example, it seemingly just decides to return void (leaving whatever garbage was previously in the return value register for the caller to discover). But it could also have assumed that main must infinitely loop (since there’s no return statement), and omitted the return instruction altogether causing execution to “fall off” the end of the function into whatever happened to be next in memory.
You are right. There are still a lot of so-called developers who cannot understand the concept of _undefined_ behavior.
As for your example:
int foo(int x) { if (x >= 0) return 123; if (x < 0) return 456; }
that has undefined behavior only if the caller uses the value. (That's to cater to ancient C code written before the void type was introduced.)
"A return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument. If the main function executes a return that specifies no value, the termination status returned to the host environment is undefined."
The ISO C++ Standard dictates that if main fails to return a result, the program result is zero. And, g++ does this.
[Edit: I'm wrong... with "gcc -ansi -std=c90", with or without optimization, I get the 13! But not 10.]
The C compiler optimizer replaces printf("Hello World!\n") with puts("Hello World!\n") and the implicit return from main() changes from 13 (the return value of printf) to 10 (the return value of puts)