On 7/1/2012 2:27 PM, Stefan Ram wrote:
> Tim Rentsch <> writes:
>> unsigned
>> unsigned_abs( int n ){
>> return n >= 0 ? n : -(n+1) + 1UL;
>> }
>> Note that for implementations where UINT_MAX == INT_MAX,
>> and where INT_MIN == -INT_MAX - 1 (which must be two's
>> complement), there is no unsigned int value that's right.
>> Under these conditions, unsigned_abs( INT_MIN ) gives zero.
>> In all other cases it gives the right value.
>
> I was asking because some implementations of »itoa« start
> with something like:
>
> if( n < 0 ){ n = -n; *p++ = '-'; }
>
> , but then seem to fail sometimes for INT_MIN.
>
> I was wondering whether there is a portable implementation
> that will be correct for all int values.
PJ Plauger's "The Standard C Library" shows one way to handle
the task, in the underpinnings of printf() et al. Basically, he
converts a negative value to `unsigned long', negates that value
in `unsigned long' arithmetic, and uses the result to produce the
leading digit. Then he strips the leading digit from the value
being converted (without the leading digit it must be >LONG_MIN)
and proceeds straightforwardly through any remaining digits.
Another way would be to start with something like
if (n > 0) n = -n; else *p++ = '-';
.... and work in negative numbers all the way. This is a little
trickier in C90 than in C99/C11, because in the former `-13 % 10'
could be -3 or +7, while in the later Standards it is always -3.
--
Eric Sosman
d