Article View: comp.lang.c.moderated
Article #2124Re: Evil C Contests
From: J. Kanze
Date: Fri, 01 Mar 1996 15:32
Date: Fri, 01 Mar 1996 15:32
101 lines
3724 bytes
3724 bytes
In article <4gj0rk$lqj@solutions.solon.com> sl14@crux1.cit.cornell.edu
(S. Lee) writes:
|> In article <4ghnp2$djn@solutions.solon.com>,
|> Sean 'Captain Napalm' Conner <spc@gate.net> wrote:
|> >
|> > How about a contest to "Spot the Bug/Portibility Problem"? For example, why
|> >is the following program buggy (and possibly not portable)?
|> >
|> >#include <stdio.h>
|> >#include <limits.h>
|> >#include <string.h>
|> >#include <stdlib.h>
|> >#include <ctype.h>
|> >
|> >int main(void)
|> >{
|> > long counts[CHAR_MAX];
|> > int c;
|> > int i;
|> >
|> > memset(counts,0,sizeof(counts));
|> > while((c = getchar()) != EOF)
|> > {
|> > counts[c]++;
|> > }
|> Won't work if char is signed. The array size is too small and all these
|> nastiness with negative array indices. I don't know how to classify this,
|> it is definitely portability-related, but I'd say this is a bug.
Two comments:
1. Even if char is unsigned, the array size is too small. On a typical
8 bit machine, for example, 0xff is a legal character, which will index
one beyond the end of the array. (In ISO 8859-1, 0xff is a y-umlaut.
The letter occurs in Finnish, I think. So you have a program which
seems to work, but mysteriously fails if the input is in Finnish. A case
which, I'll bet, you didn't think to test before releasing the program
to the customers:-).)
The correct definition for most machines (but see below) will be:
long counts[ UCHAR_MAX + 1 ];
2. There is no problem of negative indexes, even if char is signed.
getchar always returns a positive value (in the range 0...UCHAR_MAX
inclusive), or EOF. And the author didn't make the biginner's mistake
of assigning it to a char.
|> > for (i = 0 ; i < CHAR_MAX ; i++)
|> You're leaving out the last element here even if char is unsigned.
|> > {
|> > if (isprint(i))
|> > printf("%c:",i);
|> > else
|> > printf("%d:",i);
|> > printf("\t50l\n",counts[i]);
|> And here you have a typo.
|> This is fun, took me two false start to spot the real bad thing.
|> How to fix it? Hmm... the first one is tricky. I guess
|> long counts[UCHAR_MAX];
|> unsigned char uc;
|> and
|> while ((c = getchar()) != EOF)
|> {
|> uc = c;
|> counts[uc]++;
|> }
|> might work...
The real portability problem is what will happen on a machine where
sizeof( int ) == sizeof( char ). And if INT_MAX == CHAR_MAX. To tell
the truth, I'm not even sure what the standard says about this: getchar
returns an int in the range of 0...UCHAR_MAX, but UCHAR_MAX won't fit in
an int.
No matter what the standard says, getting the end condition of the
output loop right is going to be tricky, since UCHAR_MAX + 1 == 0.
Thus:
for ( i = 0 ; i < UCHAR_MAX + 1 ; i ++ )
doesn't execute the loop at all, and
for ( i = 0 ; i <= UCHAR_MAX ; i ++ )
is an infinite loop.
--
James Kanze (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils, études et réalisations en logiciel orienté objet --
-- A la recherche d'une activité dans une region francophone
Technical Details
Message-ID:
<4h75a2$4l6@solutions.solon.com>Path:
arc1-ca.pugleaf.net!solon.com!not-for-mailReferences:
<4fu7pp$94q@solutions.solon.com> <4g55jo$b44@solutions.solon.com> <4gfaki$1uc@solutions.solon.com> <4ghnp2$djn@solutions.solon.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!solon.com!not-for-mail From: kanze@gabi-soft.fr (J. Kanze) Newsgroups: comp.lang.c.moderated Subject: Re: Evil C Contests Date: 1 Mar 1996 09:32:18 -0600 Organization: GABI Software, Sarl. Sender: clc@solutions.solon.com Approved: clc@solutions.solon.com Message-ID: <4h75a2$4l6@solutions.solon.com> References: <4fu7pp$94q@solutions.solon.com> <4g55jo$b44@solutions.solon.com> <4gfaki$1uc@solutions.solon.com> <4ghnp2$djn@solutions.solon.com> NNTP-Posting-Host: solutions.solon.com