This is the trap with 'undefined behaviour': it has nothing to do with portability, but it is a language level definition.
I.e., if the C std says it's 'undefined', it is not to be avoided for portability reasons (hardware, assembler), but it must not be used, end of story. The portability stuff is called 'implementation defined' in C, not 'undefined behaviour'. The problem is that the compiler can (and will!) exploit undefined behaviour rules. E.g., the following code is officially broken (and not just on weird hardware, but everywhere, as defined by the C std):
int saturated_increment(int i)
{
if ((i + 1) < i) { /* if it overflows, do not inc */
return i;
}
return i + 1;
}
The compiler may (and many will) remove the whole if() block, because i+1<i is trivially false, because int cannot overflow (says the C standard).
As one can imagine, when compilers started exploiting this, a lot of discussion about sensibility followed. And gcc added -fwrapv among other things.
(And the code would be fine if 'unsigned' was used in stead of 'int', because this is only a problem of signed ints.)