New 'n' Improved comp.lang.c FAQ List
Paul Dow CRI-UK
paul at sequoia.cray.com
Thu Apr 4 20:24:53 AEST 1991
Will this never end..... Here's my three ha'pence....
In article <1991Apr4.024300.19969 at garfield.cs.mun.ca>, matthew1 at garfield.cs.mun.ca (Matthew J. Newhook) writes:
|> bls at u02.svl.cdc.com (Brian Scearce) writes:
|>
|> >grover at big-joe.cs.unlv.edu (Kevin Grover) writes:
|> >> Apparently non-obvious April Fool's Day bogus account posts:
|> >>> Q: Why doesn't this function work:
|> >>>
|> >>> itoa(int i)
|> >>> {
|> >>> char retbuf[5]; /* biggest int: 32769 */
|> >>> sprintf("%d", retbuf, i);
|> >>> return retbuf;
|> >>> }
|> >>>
|>
|> >> A correct version of this program is:
|> >> char *itoa(int i)
|> >> {
|> >> static char retbuf[5]; /* biggest int: 32769 */
|> >> sprintf(retbuf, "%d", i);
|> >> return retbuf;
|> >> }
|>
|> >Almost, but not quite, Mr. Grover. The *really* correct version of this:
|>
|> > char *itoa(int i)
|> > {
|> > static char retbuf[5]; /* biggest int: 32768 */
|> > sprintf(retbuf, "%d", i);
|> > return retbuf;
|> > }
|>
|> Actually here is a correct (portable) version (assuming that you want to
|> keep a static character buffer, and not use a newly malloc'd one each time).
|>
|> #include <math.h>
|>
|> char *itoa(int i)
|> {
|> static int first = 1;
|> static char *s;
|>
|> if (first) { /* IF FIRST TIME ALLOCATE MEMORY FOR STRING */
|> first = 0;
|> s = (char *)
|> malloc((long) ceil(log10(pow(2, (double) sizeof(int) * 8))) +1);
|> if (!s) {
|> fprintf(stderr,"malloc failed\n");
|> exit(1);
|> }
|> }
|>
|> sprintf(s, "%d", i);
|> return s;
|> }
|>
|> This is portable, 'cause it always assigns the correct value to the size of
|> the array, without depending on the sizeof(int) == 2.
|>
|> Matthew Newhook
|>
It is easy to say that things are "correct" & "portable". How often have
people been flamed in this newsgroup (and others) for that. A lot of people
are put of replying to questions for fear of being flamed. Mind you, if
the replies were framed as suggestions as opposed to "correct"/"portable" etc,
then they would not irritate the "flamer" so much.
Anyhow, enough of that sideline, let us look at the last example above and ask
a few questions ?
Q1) The "*8" I presume is for the numbers of bits in a byte. Are there
problems here on a 9 bit machine? I don't have access to any such machines, so I cannot test this out.
Q2) Should the first parameter to pow() be a double - the compiler may not
support prototypes.
Q3) The "+1" appears to be for the terminating NULL character. Has any
space being allowed for a leading "-" sign ?
Q4) Malloc is being passed a "long" type for the number of bytes. Should
this be an unsigned (int) [it is on my SunOS 4.1 system].
Q5) If the malloc fails, then a string is written to stderr. Is this
accetable? Is it also acceptable to exit at that point ?
This may not be acceptable to some applications which might not support a
stderr per se ["stderr" might exist, but is it valid to use it ?].
I have encountered this problem with assrted C libraries on several
systems.
I have to admit that it is good to see return values checked. Code that
ignores return values is the bane of my life.
Suggestions:
Here are a few things that I would think about. They would not change the functionality, but may be worth considering - depending on ones viewpoint.
S1) I would tend to use a NULL/not NULL test for the pointer to determine if
the buffer needed to be allocated.
S2) It took a bit of thinking about to work out what the
malloc((long) ceil(log10(pow(2, (double) sizeof(int) * 8))) +1);
was doing. Can this be simplified ?
S3) It took me a second or two to work out where the result of the malloc was
going. It would have helped me of the malloc line was indented more.
Paul.
[All disclaimers may be assumed]
More information about the Comp.lang.c
mailing list