Path: utzoo!attcan!uunet!seismo!sundc!pitstop!sun!decwrl!labrea!rutgers!deimos!uxc!uxc.cso.uiuc.edu!uxg.cso.uiuc.edu!uicsrd.csrd.uiuc.edu!mcdaniel From: mcdaniel@uicsrd.csrd.uiuc.edu Newsgroups: comp.lang.c Subject: Re: gurulet aptitude test (and bug) Message-ID: <44200023@uicsrd.csrd.uiuc.edu> Date: 11 Dec 88 00:40:00 GMT References: <228@celerity.UUCP> Lines: 92 Nf-ID: #R:celerity.UUCP:228:uicsrd.csrd.uiuc.edu:44200023:000:3923 Nf-From: uicsrd.csrd.uiuc.edu!mcdaniel Dec 10 18:40:00 1988 I'm not a Gwyn/Torek/Harris-level guru, but I'll give it a shot. Written 6:38 pm Dec 8, 1988 by jpa@celerity.UUCP in comp.lang.c: > Please don't send me mail to tell me what the problem is ^^^ I count 12 problems with the code. I suppose that the basis of the problem is that the code was > a contrived example (as you put it) and was not linted. Actually, not all the problems are "bugs" per se; some are just bad style. In this list, "struct zztop {" is designated line 1: I The program has no side-effects; a "decent" optimizer should dead-code the entire program. :-) However, a "decent" compiler wouldn't compile this program at all. II Line 4: the declaration of "struct zztop" was probably meant to have a ";" after the closing "}". Without it, sub1()'s return type is "struct zztop": struct zztop {int a; int b;} sub1() {...} With a ";", sub1()'s return type is an int. This point is irrelevant, really, since sub1's return value is always ignored. III Line 5 is an comment, but what it says is obvious from inspection. Comments like i++; /* Increment i */ ought to be avoided. OK, I'll admit this one is reaching pretty far . . . :-) IV Line 10, "zz.a = 0x77777777;", is non-portable. If "int"s are 16 bits long, the result of assigning 0x77777777 (presumably a long) to the int zz.a is implementation-defined. V Line 12: sub1() is declared above as returning a value. However, no "return" statement is ever used in sub1(). It's not a bug because the return value of sub1() is never used. However, if a function doesn't return a value, I prefer to declare it "void". VI Line 13 has the first bug. Line 11 implies that sub2 is a function of one argument (a struct zztop) returning int. Line 13 defines sub2 as a function of NO arguments, returning int. I'm not surprised that a coredump occurs. VII Line 16 is like line 10 (unportable to 16-bit machines). VIII Line 17: parentheses are no longer needed following "return". Some always use them, some don't. I don't. It's more or less a religious issue. IX Line 17: sub2() returns 0x77777777, but sub2()'s return type is int. This will fail on 16-bit machines. X sub2()'s return value is always ignored. XI Line 22: the other unequivocal bug. Above, sub1 was defined as a function returning int but taking no arguments. Here, one argument is passed in. XII The program does not "exit()", nor does "main" return with a value. On some systems, that means that the program exits with an undefined exit status, which is probably non-zero. If this program were invoked in a Bourne-shell script under "set -e", or C-shell using "csh -e", the shell script would abort. Always use "exit(expression)", or use "return expression;" in main(). Lint picks up many of these problems: lint -phbxac bug.c bug.c: bug.c(10): warning: long assignment may lose accuracy bug.c(16): warning: long assignment may lose accuracy bug.c(17): warning: long assignment may lose accuracy sub2: variable # of args. bug.c(14) :: bug.c(11) sub1: variable # of args. bug.c(8) :: bug.c(22) sub1 value is used, but none returned <<< 1 sub2 returns value which is always ignored _iob used( llib-port(25) ), but not defined <<< 2 The messages marked "1" and "2" are spurious, but the rest are fine. -- Tim, the Bizarre and Oddly-Dressed Enchanter Center for ||| Internet, BITNET: mcdaniel@uicsrd.csrd.uiuc.edu Supercomputing ||| UUCP: {uunet,convex,pur-ee}!uiucuxc!uicsrd!mcdaniel Research and ||| ARPANET: mcdaniel%uicsrd@uxc.cso.uiuc.edu Development, ||| CSNET: mcdaniel%uicsrd@uiuc.csnet U of Illinois ||| DECnet: GARCON::"mcdaniel@uicsrd.csrd.uiuc.edu"