unsigned and signed are not different on a bit level, either one can be interpreted as the other. It counts what you tell the compiler, in this case, you pass it to str_for_int(), which expected a signed integer. The compiler will just pass your unsigned integer and the function will treat is as signed. Same with %d, which is the format specifier for a signed integer.
Of course, for the least significant bit to be affected in the first place, you'd have to subtract two pointers that are both at either end of the heap, and I have my doubts that you have such a continuous block of memory anywhere.