At least one reason why it’s UB is that string.h
can introduce macros. For internal implementation reasons, those macros might have been written on the assumption that strcmp
is the “real” strcmp function. If you define strcmp
to be something else and then use those macros, strcmp
will expand to my_strcmp
in the macros, with unexpected consequences.
Rather than try to work out exactly what code would be OK in the ...
and what would not, the standard puts an early stop to your shenanigans.
Also note that aside from the fact that the standard flat-out forbids it, your #define strcmp my_strcmp
might be a macro re-definition, because string.h
is permitted to do #define strcmp __strcmp
or whatever. So on some conforming implementations your code is ill-formed.