Re: Newbie - itoa implementation redux



Andrew Poelstra wrote:
On 2006-08-15, Eric Sosman <Eric.Sosman@xxxxxxx> wrote:

Andrew Poelstra wrote On 08/15/06 17:00,:
[...]
This whole section could be replaced with:
int neg = (a < 0);
and placed above the previous line, which would become:
unsigned abs_a = neg ? -a : a;

This is much more compact, and IMHO, clearer.

... and perpetuates the same bug. As in the original,
evaluating `-a' when `a < -INT_MAX' can have undesirable
consequences.

It will result in a being 0, correct? Is there any case where that would
not be true?

It is possible that the result might be zero -- or forty-two,
or eleventy-one, or massive memory meltdown. Section 6.5, para 5:

"If an /exceptional condition/ occurs during the
evaluation of an expression (that is, if the result
is not mathematically defined or not in the range of
representable values for its type), the behavior is
undefined."

So: If `a' is less than `-INT_MAX', then `-a' is greater than
`INT_MAX', which means it's outside the range of representable
values of `int'. The fact that the result (whatever it might
be) is later converted to `unsigned int' is of no consequence;
the damage has already occurred.

This can't happen on signed-magnitude or ones'-complement
systems, but it does happen on two's-complement machines where
`INT_MIN' equals `-INT_MAX-1'. Most implementations simply
ignore the overflow and produce the low-order bits of the too-
wide result, after which conversion to `unsigned int' will give
the "right" answer (which is certainly not zero). This outcome
is not guaranteed, though, and I have used machines that trapped
on integer overflow (granted, I wasn't using C).

And more importantly, how would one fix this bug? Since there's no type
guaranteed to be wider than an unsigned int, you'd have to handle negative
numbers as they are... which makes me wonder why it is necessary to take
the absolute value at all!

It's not necessary. In "The Standard C Library" P.J. Plauger
shows how to do the conversion by using non-positive numbers. His
code is a bit cumbersome because of C89's wishy-washiness about
how negative values work with the division and modulus operators;
C99 has tightened this up and his code could now be simplified.

The O.P.'s code had a comment showing a method that will work
on every machine I've run across:

> abs_a = -a ; //(1U - (1U + a));

.... and I think that changing it to `1U - (1 + a)' would make it
completely bullet-proof. (The issue: UINT_MAX is required to be
at least as large as INT_MAX, but I don't think it's required to
be larger -- although it has been on every machine I've used.)

str[--i] = 0;

This is only necessary in *your* version of the code;
it was not needed in the original.


Really? Where in the original is str[] null-terminated?

The original str[] has static duration and no explicit
initializer, hence it's initialized to all-elements-zero
before the program starts operating.

My personal preference would be to do it your way, just
in case a caller overwrites the '\0' at the end of the returned
string, leaving a time bomb for subsequent callers. Better to
refresh the '\0' each time than to hope it never gets clobbered --
still, as the code stood the '\0' was already present.

--
Eric Sosman
esosman@xxxxxxxxxxxxxxxxxxx
.



Relevant Pages

  • Re: Questions, please
    ... a negative number to an `unsigned int', ... Of course not: the *conversion* from `double' ... > reason it allows it is to avoid breaking hundreds of pre-standard programs. ... on these machines the cast ...
    (comp.lang.c)
  • Re: Cohens paper on byte order
    ... > I've said over and over that the minor issue with AES exists. ... conversion if communication of byte array is between ... machines involved are of the two different types. ... The byte arrays of AES output ...
    (sci.crypt)
  • Re: Bypassing the conversion wizard
    ... machines running Windows XP SP3. ... The suggestion I'm currently working on is to build an MFC skeleton and then ... LINK: fatal error LNK1123: failure during conversion to COFF: file ... prepared to dispense with that too if it will get the program to build since ...
    (microsoft.public.vc.mfc)
  • Re: if(a);
    ... The type of the octal signed int literal 0 will be compared to the ... 'a' has type unsigned int, in which case 0 is converted to ... is still 0 after undergoing conversion, ...
    (comp.lang.c)
  • Re: print hex value of char
    ... The %x format is for printing unsigned int. ... do cause an actual conversion, but then the actual promoted type to ... If any argument is not the correct type for the corresponding ... suggests that it is undefined behaviour. ...
    (comp.lang.c)