Morris Dovey wrote On 07/18/06 10:07,:
Eric Sosman (in (e-mail address removed)) said:
| Morris Dovey wrote:
|
|| char *itos(char *s,int i)
|| { char *r = s;
|| int t;
|| if (i < 0)
|| { i = -i;
|| *s++ = '-';
|| }
|| t = i;
|| do ++s; while (t /= 10);
|| *s = '\0';
|| do *--s = '0' + i % 10; while (i /= 10);
|| return r;
|| }
||
|| Will convert i to a properly terminated digit string beginning at s
|| and will prepend a '-' if the value of i is less than zero. It will
|| return a pointer to the start of the string.
|
| Something's strange: On my machine this works most of
| the time, but once it gave "-./,),(-*,(" as the digit string.
| Any idea why? (The value of i was negative and large when
| the peculiar output occurred: -2147483648, to be precise.)
Interesting indeed. Could it have been a problem with the target
string area not being large enough to contain the result string? Even
at the boundary point where i = -i might produce a problem, I would
still expect to see an initial sequence of digits.
The problem value is 0xFFFFFFFF80000000 - so there might be a problem
with division of the largest int value if your int size is 32.
It is strange.
Not so very strange, actually (I was attempting irony,
but apparently only achieved rust-y ...). The problem is
that INT_MIN may have no corresponding positive int value,
so the computation of `-INT_MIN' overflows. What happens
next is up to the implementation, but on two's complement
systems it is often the case that `-INT_MIN' produces the
value INT_MIN all over again. If this happens, `i = -i'
in the code above does not produce a positive value; `i'
will still be large and negative.
The next piece of the puzzle depends on the behavior
of the modulus operator with negative numbers. In C90, it
is conceivable that you could get lucky: `-13 % 10' could
produce 7 as a result, if `-13 / 10' produces -2. But C90
also allows `-13 % 10' to produce -3 and `-13 / 10' to
produce -1. C99 tightened the rules to *require* the latter,
in part for consistency with other languages and in part
because practically every implementation already did it that
way anyhow. So it's almost a sure bet that `negative % 10'
produces a remainder somewhere between -9 and 0.
The weird characters I reported happen to have (on my
system) encodings that lie just before that of the digit '0'.
Strangeness explained.
To make a long story short: "Emit a minus sign and then
convert the absolute value" is *not* a reliable strategy
for converting integers to digit strings.