[comp.lang.c] lint won't verify printf formatting against variable types??

stever@tree.UUCP (Steve Rudek) (06/23/89)

I was surprised to discover that neither cc nor lint comments when printf
formatting doesn't match variable types--I thought lint complained about
everything!  In other words, lint won't comment on the following:
int x;
long y;
printf ("x=%ld y=%d", x, y);

I'm trying to get a game called "conquer" to work on a Microport SysV/AT
machine where ints are 16 bits rather than the 32 bits the author expected.
After wrestling with variable overflow for a while, I figured the "good enough"
solution would be to just change most int definitions to INT and #define
INT as long.  Then I would count on cc or lint to detect all the %d formatting
which needed to be changed to %ld.  Wrongo.  cc and lint are both completely
blind to the misformatting!  I find that incredible.  Oh, I understand that
the formatting argument to printf is just a string pointer, but I'm aghast
that there appears to be no easy way to detect what must be a super common
coding bug!  The printf family is enough of a fixture in the C language and
this is a common enough sort of error that lint really should be responsible
for catching this sort of misformat.

Am I missing something or do I really need a custom program to detect this
kind of mistake?  If so, do I have to write it myself or has someone out
there already written the program??

P.S. Can anyone direct me to Ed Barlow, the author of "conquer", or to the
latest version?  I'm hacking on version 2.2.
-- 
----------
Steve Rudek  {ucbvax!ucdavis!csusac OR ames!pacbell!sactoh0} !tree!stever

ked@garnet.berkeley.edu (Earl H. Kinmonth) (06/24/89)

In article <328@tree.UUCP> stever@tree.UUCP (Steve Rudek) writes:

>I was surprised to discover that neither cc nor lint comments when printf
>formatting doesn't match variable types--I thought lint complained about
>everything!  In other words, lint won't comment on the following:
>int x;
>long y;
>printf ("x=%ld y=%d", x, y);
>
>I'm trying to get a game called "conquer" to work on a Microport SysV/AT
>machine where ints are 16 bits rather than the 32 bits the author expected.

One way to make sure code like this is reasonably portable is to always
write the format statement with casts.

printf ("x=%ld y=%d", (long) x, (int) y);

or preferably

printf ("x=%ld y=%ld", (long) x, (long) y);

A superfulous cast does not harm.  Casting to a larger size makes sure
nothing will be lost.

chris@mimsy.UUCP (Chris Torek) (06/24/89)

In article <328@tree.UUCP> stever@tree.UUCP (Steve Rudek) writes:
>I was surprised to discover that neither cc nor lint comments when printf
>formatting doesn't match variable types ....

There are a whole bunch of `cc's and `lint's.  The lint in 4.3BSD-tahoe
*does* complain, courtesy of Arthur Olson (uunet!elsie!ado).  Become a
student at your nearby University, get an account on a Tahoe or VAX
running 4.3-tahoe, and lint your programs there. :-)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

jagardner@watmath.waterloo.edu (Jim Gardner) (06/24/89)

Not this this will help you, but we just put this kind of checking into
our (ANSI aspiring) compiler. I'm sure there are many other vendors who
will be doing (or have done) this, since your's is a common complaint.
Maybe you can bash on the gcc people for it...

David Tanguay

buck@siswat.UUCP (A. Lester Buck) (06/26/89)

In article <328@tree.UUCP>, stever@tree.UUCP (Steve Rudek) writes:
> I was surprised to discover that neither cc nor lint comments when printf
> formatting doesn't match variable types--I thought lint complained about
> everything!  In other words, lint won't comment on the following:
> int x;
> long y;
> printf ("x=%ld y=%d", x, y);
> 
> I'm trying to get a game called "conquer" to work on a Microport SysV/AT
> machine where ints are 16 bits rather than the 32 bits the author expected.

The Nutshell handbook "Checking C Programs with Lint" discusses this
problem.  Until we all have versions of lint that handle /*PRINTFLIKEn*/,
you might try using the program printfck.  "Andries Brouwer wrote this as a
quick hack to check the Hack & Quest sources."  It rewrites each printf-like
call to have the arguments as return values from functions, and then
includes a lint library for each function type.  This program, and several
more lint helper programs, are available from uunet!~/nutshell/lint/*.

I was writing some drivers on an RT under AIX 2.2.1 recently and had been
running them through lint regularly (after cobbling together a lint library
for kernel routines).  Then I was reading the Nutshell handbook above and
picked up one of the extended checkers (the one called "check", if I
remember).  It reported that I had a nested comment in the source, but I
thought that was rather odd.  Then I noticed that the nested comment was
reported in the system header file!#%$  Sure enough, here is a piece of
/usr/include/sys/kio.h from AIX/RT 2.2.1:

[ declaring a struct query ]

	caddr_t ccb;
	long ioard;
	union {
		struct {                /* disk device mini disk and floppy */
			long blk_num;    /* block # of last operation */
			long num_blks;   /*
				       ^^^^^^^
			char blk_size;   /* block size */
			char dev_add[3]; /* 24 bit physical device address */
			} vd;
		struct {                /* floppy device */
			long blk_num;    /* block # of last operation */
			char byte_sec;  /* bytes per sectors */
			char sec_track; /* sectors/track */
			char track_cyl; /* tracks per cylinder */
			char num_cyl;   /* number of cylinders */
			char blk_size;  /* block size in bytes */
			char res;
			ushort steprate;
			} fd;
		struct {                /* rs232 device */
			char c1;

Such discoveries send a chill down my spine.  I can think of several
possibilities, all bad, but the most likely is that the released version of
the headers is separated at some point from the "one true source" for AIX.
What other subtle bugs might have crept in with such a source code control
system?  Does this happen in other versions of Unix?

-- 
A. Lester Buck		...!texbell!moray!siswat!buck

bob@omni.com (Bob Weissman) (06/27/89)

Last week I spent an entire day tracking down one of those bugs you just
don't see after staring at your code too long.  It was of the form:

	if (condition);
	    action;

My lint (SunOS 4.0.1 version) did not flag the extra semicolon.

I Hate C.


-- 
Bob Weissman
Domainish: bob@omni.com
UUCPish:   ...!{amdahl,apple,pyramid,tekbspa,uunet}!koosh!bob

hacker@isadora.ikp.liu.se (Goran Larsson [Hacker of Hackefors]) (06/28/89)

In article <105@borabora.omni.com> bob@omni.com (Bob Weissman) writes:
>Last week I spent an entire day tracking down one of those bugs you just
>don't see after staring at your code too long.  It was of the form:
>
>	if (condition);
>	    action;

It's your own fault -- you should have written it as
	if ( condition ) {
		action;
	}
to reduce the risk of errors!

>My lint (SunOS 4.0.1 version) did not flag the extra semicolon.

It isn't supposed to find this "error" as it is legal C.

>I Hate C.

I Love C

  !       _
  ! !    Goran Larsson  [The Hacker of Hackefors]
--+-!    Hackefors, Linkoping, SWEDEN (See)  +46 13-155535 (Hear)
  !-+--  ...!uunet!sunic!liuida!prodix!isadora!hacker (UUCP)
  ! !    hacker@isadora.ikp.liu.se (Internet)
    !

ejd@caen.engin.umich.edu (Edward J Driscoll) (06/28/89)

In article <411@isadora.ikp.liu.se> 
hacker@isadora.ikp.liu.se (Goran Larsson [Hacker of Hackefors]) writes:
>In article <105@borabora.omni.com> bob@omni.com (Bob Weissman) writes:
>>Last week I spent an entire day tracking down one of those bugs you just
>>don't see after staring at your code too long.  It was of the form:
>>
>>	if (condition);
>>	    action;
>
>>My lint (SunOS 4.0.1 version) did not flag the extra semicolon.
>
>It isn't supposed to find this "error" as it is legal C.
>

It is legal, but I would hope for a warning from such an obvious
semantic error.  I don't use lint much, but Borland TC 2.0 will
warn you about some *legal* constructs like "if(x = 5)".  Oddly, I
just tried it and it also lets "if(x==5);" get by without a peep.
Oh well.

>>I Hate C.
>
>I Love C
 ^^^^^^^^^^^---->me too


-- 
Ed Driscoll
The University of Michigan
ejd@caen.engin.umich.edu

bbadger@x102c.harris-atd.com (Badger BA 64810) (06/29/89)

In article <27729@lll-winken.LLNL.GOV> berry@lll-crg.llnl.gov (Berry Kercheval) writes:
>In article <441a30e5.8f55@fiero.engin.umich.edu>, ejd@caen (Edward J Driscoll) writes:
>>It [[ if(x==5); ]]is legal, but I would hope for a warning from such an 
>> obvious semantic error.  
>
>Goodness, save me from useless warnings for perfectly good C
>constructs.  This is NOT an "obvious" semantic error.  Have you never
>done something like this?
>
>	/* skip to end of word */
>	while(!isspace(*cp++));
>
>Admittedly, I usually code it as:
>
>	while(!isspace(*cp++))
>		/* null */ ;
>
>but it's very useful at times.
>
>  --berry

However,
	if(x==5); 
most certainly is useless, in fact, 
	if(<<expression>>);  
is *completely* equivalent to 
	<<expression>>;
semantically.  This isn't true for ``while(<<expression>>);'', in general.
Since this is an obvious abuse of syntax, I would *hope* --
but not necessarily *expect* -- that lint would catch such an error.  
It is something which could be added to the list of probable errors which 
lint should check for.  Because it is so easy to habitually add a ';' to the
end of a statement, it's an easy trap.

Give the guy a break -- he didn't say he expected ``cc'' to catch it, he 
just hoped that ``lint'' would.  That's lint's job: finding *legal* constructs
which aren't portable or probably aren't what was intended.

Bernard A. Badger Jr.	407/984-6385          |``Use the Source, Luke!''
Secure Computer Products                      |``Get a LIFE!''  -- J.H. Conway
Harris GISD, Melbourne, FL  32902             |Buddy, can you paradigm?
Internet: bbadger%x102c@trantor.harris-atd.com|'s/./&&/g' Tom sed expansively.

bob@omni.com (Bob Weissman) (06/30/89)

In article <27729@lll-winken.LLNL.GOV>, berry@lll-crg.llnl.gov (Berry Kercheval) writes:
> In article <441a30e5.8f55@fiero.engin.umich.edu>, ejd@caen (Edward J Driscoll) writes:
> >It [[ if(x==5); ]]is legal, but I would hope for a warning from such an 
> > obvious semantic error.  
> 
> Goodness, save me from useless warnings for perfectly good C
> constructs.  This is NOT an "obvious" semantic error.  Have you never
> done something like this?
> 
> 	/* skip to end of word */
> 	while(!isspace(*cp++));

Sorry, but "while" is quite different from "if".

I'm not talking about
	random_keyword (expression);

I'm talking about
	if (expression);
which, while legal, *never* makes sense semantically, as it is always
equivalent to
	expression;

OK?

-- 
Bob Weissman
Domainish: bob@omni.com
UUCPish:   ...!{amdahl,apple,pyramid,tekbspa,uunet}!koosh!bob

Horne-Scott@cs.yale.edu (Scott Horne) (06/30/89)

In article <27729@lll-winken.LLNL.GOV>, berry@lll-crg (Berry Kercheval) writes:
> In article <441a30e5.8f55@fiero.engin.umich.edu>, ejd@caen (Edward J Driscoll) writes:
> >It [[ if(x==5); ]]is legal, but I would hope for a warning from such an 
> > obvious semantic error.  
> 
> Goodness, save me from useless warnings for perfectly good C
> constructs.  This is NOT an "obvious" semantic error.  Have you never
> done something like this?
> 
> 	/* skip to end of word */
> 	while(!isspace(*cp++));

You're missing the point.  `if(x == 5);' is not necessarily a semantic error,
but it probably is.

`while' constructs with null bodies are useful, but `if' constructs like the
one above are not.  Consider what `if(x == 5);' does:  *nothing*!  If x == 5,
the program continues; if x != 5, the program continues the same way.  There
aren't even any side effects; but even if there were, they would be obtained
just the same with out the `if'.  I'm sure you'll have a hard time thinking
of an occasion in which a reasonable programmer would write `if(x == 5);'
intentionally.

However, I would of course *allow* such constructs, and I think that the
compiler should give at most a warning.  Such things are best left to
programs like `lint'.

					--Scott

Scott Horne                              Hacker-in-Chief, Yale CS Dept Facility
horne@cs.Yale.edu                         ...!{harvard,cmcl2,decvax}!yale!horne
Home: 203 789-0877     SnailMail:  Box 7196 Yale Station, New Haven, CT   06520
Work: 203 432-6428              Summer residence:  175 Dwight St, New Haven, CT
Dare I speak for the amorphous gallimaufry of intellectual thought called Yale?

berry@lll-crg.llnl.gov (Berry Kercheval) (06/30/89)

In article <2271@trantor.harris-atd.com>, bbadger@x102c (Badger BA 64810) writes:
>In article <27729@lll-winken.LLNL.GOV> berry@lll-crg.llnl.gov (Berry Kercheval) writes without thinking....:
>>constructs.  This is NOT an "obvious" semantic error.  
>
>Give the guy a break -- he didn't say he expected ``cc'' to catch it, he 
>just hoped that ``lint'' would.  That's lint's job: finding *legal* constructs
>which aren't portable or probably aren't what was intended.


Yeah, you're right.  I focused on the 'useless null statement' and
didn't consider when it's useful and when it isn't.  Of course, I
figured this out on the way home last night when it was too late...

Just to save myself anymore angry mail telling me how stupid I was, let me
summarize what we seem to agree on:

	"if( expr );" is useless, but legal, and a case can be made for
	issuing a warning if it's detected, but it should not be forbidden.

OK?

  --berry

	

karl@haddock.ima.isc.com (Karl Heuer) (06/30/89)

In article <115@borabora.omni.com> bob@omni.com (Bob Weissman) writes:
>I'm talking about
>	if (expression);
>which, while legal, *never* makes sense semantically

Well, some versions of |<assert.h>| do this deliberately.  (But these should
be fixed anyway, since the pANS requires |assert()| to be a void-valued
expression macro, and it's not hard to do this.)  And I have, myself, used a
null-bodied |if| with an |else| clause, in situations where this was clearer
than a straight |if| with the condition inverted.

It would be within the "spirit of lint" to warn about *all* null statements,
provided (a) any instance can be silenced with the lintpragma |/*NULL*/|, and
(b) the warning can be disabled by a command-line option.  (Probably |if| and
|while| should have separate flags, since many people depend on null-bodied
|while|.)

Why warn about null |while| at all?  Because it's *possible* that it's a typo,
just as with |if|; and those of use who never write it that way would be able
to make good use of the warning.  (Some of us always use |/*NULL*/|, or use
empty braces instead of a semicolon, or write |do; while (ex);| whenever the
entire loop is contained in the test.)

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
________
Note: I'll be out of town July 2-22, so I probably won't be able to reply to
any followups.  If you send me mail, include enough context that I'll still
remember the thread three weeks later.

diamond@diamond.csl.sony.junet (Norman Diamond) (06/30/89)

In article <105@borabora.omni.com> bob@omni.com (Bob Weissman) writes:

>Last week I spent an entire day tracking down one of those bugs you just
>don't see after staring at your code too long.  It was of the form:
>	if (condition);
>	    action;
>My lint (SunOS 4.0.1 version) did not flag the extra semicolon.
>
>I Hate C.

This is one of many defects in C, but remember that C used to be
experimental and remember what its predecessors were like.  C was one
of the world's best programming languages 15 years ago.  You should
not hate C.  You should only hate the people who force us to continue
using it, 15 years after such defects are known.

--
Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net)
 The above opinions are claimed by your machine's init process (pid 1), after
 being disowned and orphaned.  However, if you see this at Waterloo, Stanford,
 or Anterior, then their administrators must have approved of these opinions.

arrom@aplcen.apl.jhu.edu (Ken Arromdee) (06/30/89)

if (f1(a)) /* do nothing */ ;
else if (f2(a)) {
	/* some code */
} else if (f3(a)) {
	/* some code */
} else if (f4(a)) {
	/* some code */
}

Now suppose that f1 through f4 are all conceptually related.  Claim: this
is clearer than the other way (with f2, f3, f4 all inside an if (!f1(a))).
Or at least, if it's not obviously clearer, it's not obviously unclear
either and can be considered a legitimate use of "if (condition) ;".
(Of course it should always be commented though.)
--
"The fact is self evident from the text and requires no supporting argument."
  --Tim Maroney

Kenneth Arromdee (UUCP: ....!jhunix!ins_akaa; BITNET: g49i0188@jhuvm;
     INTERNET: arromdee@crabcake.cs.jhu.edu) (please, no mail to arrom@aplcen)

hacker@isadora.ikp.liu.se (Goran Larsson [Hacker of Hackefors]) (06/30/89)

In article <441a30e5.8f55@fiero.engin.umich.edu> ejd@caen.engin.umich.edu (Edward J Driscoll) writes:
>In article <411@isadora.ikp.liu.se> hacker@isadora.ikp.liu.se (Goran Larsson [Hacker of Hackefors]) writes:
>>In article <105@borabora.omni.com> bob@omni.com (Bob Weissman) writes:
>>>Last week I spent an entire day tracking down one of those bugs you just
>>>don't see after staring at your code too long.  It was of the form:
>>>	if (condition);
>>>	    action;
>>>My lint (SunOS 4.0.1 version) did not flag the extra semicolon.
>>It isn't supposed to find this "error" as it is legal C.
>It is legal, but I would hope for a warning from such an obvious
>semantic error.  I don't use lint much, but Borland TC 2.0 will
>warn you about some *legal* constructs like "if(x = 5)".  Oddly, I
>just tried it and it also lets "if(x==5);" get by without a peep.

The statement "if(expr);" can be very useful sometimes. In the sources for
the standalone programs (and in the kernel too I think) on my workstation, the
watchdog is kicked with the statement "if(*((char*)0x80007));" and after
optimization this becomes "tstb 0x80007" (68k) wich is as small and fast
as it possibly can be! Personally I would rather write this as
	if ( expr ) {
		/*VOID*/
	}
to reduce the risk for missunderstanding.

  !       _
  ! !    Goran Larsson  [The Hacker of Hackefors]
--+-!    Hackefors, Linkoping, SWEDEN (See)  +46 13-155535 (Hear)
  !-+--  ...!uunet!sunic!liuida!prodix!isadora!hacker (UUCP)
  ! !    hacker@isadora.ikp.liu.se (Internet)     _
    !    This signature is Cosylight (C) 1989 by Goran Larsson

hacker@isadora.ikp.liu.se (Goran Larsson [Hacker of Hackefors]) (06/30/89)

In article <115@borabora.omni.com> bob@omni.com (Bob Weissman) writes:
>I'm talking about
>	if (expression);
>which, while legal, *never* makes sense semantically, as it is always
>equivalent to
>	expression;
>
>OK?

NO, NO, NO, NO!

It does make sense sometimes, take this for example:

#define WATCHDOG {if (*( (char *)0x80007 ));}

Whenever you use this macro it will be compiled as "tstb 0x80007" (68k)
wich is the smallest and fastest way of kicking the watchdog without side
effects (assignment to dummy variable etc.)

Talking about equivalence, I cant see that
	if (*( (char *)0x80007 ));
is equivelant to
	*( (char *)0x80007 );
as the later does not generate any code at all!

  !       _
  ! !    Goran Larsson  [The Hacker of Hackefors]
--+-!    Hackefors, Linkoping, SWEDEN (See)  +46 13-155535 (Hear)
  !-+--  ...!uunet!sunic!liuida!prodix!isadora!hacker (UUCP)
  ! !    hacker@isadora.ikp.liu.se (Internet)     _
    !    This signature is Cosylight (C) 1989 by Goran Larsson

paul@moncam.co.uk (Paul Hudson) (06/30/89)

To: 
In article <27729@lll-winken.LLNL.GOV> berry@lll-crg.llnl.gov (Berry Kercheval) writes:

   >It [[ if(x==5); ]]is legal, but I would hope for a warning from such an 
   > obvious semantic error.  

   Goodness, save me from useless warnings for perfectly good C
   constructs.  This is NOT an "obvious" semantic error.  Have you never
   done something like this?

	   /* skip to end of word */
	   while(!isspace(*cp++));

   Admittedly, I usually code it as:

	   while(!isspace(*cp++))
		   /* null */ ;

But the first *is* a semantic error - x== 5 has no side-effects
(assuming x isn't volatile). A compiler can check for this before
warning about the null statement.

And in this particular case "if (expre);" is always equivalent to
"expr;" - and is IMHO likely to be a programmer error, so it should be
warned about.
--
Paul Hudson	 MAIL: Monotype ADG, Science Park, Cambridge, CB4 4FQ, UK.
		PHONE: +44 (223) 420018	  EMAIL: paul@moncam.co.uk,
	;"	  FAX: +44 (223) 420911		 ...!ukc!acorn!moncam!paul
 `"";";"        "/dev/null full: please empty the bit bucket"

jmm@eci386.uucp (John Macdonald) (07/01/89)

In article <2271@trantor.harris-atd.com> bbadger@x102c.harris-atd.com (Badger BA 64810) writes:
>In article <27729@lll-winken.LLNL.GOV> berry@lll-crg.llnl.gov (Berry Kercheval) writes:
>>In article <441a30e5.8f55@fiero.engin.umich.edu>, ejd@caen (Edward J Driscoll) writes:
>>>It [[ if(x==5); ]]is legal, but I would hope for a warning from such an 
>>> obvious semantic error.  
>>
>>Goodness, save me from useless warnings for perfectly good C
>>constructs.  This is NOT an "obvious" semantic error.  Have you never
>>done something like this?
>>
>>	/* skip to end of word */
>>	while(!isspace(*cp++));
>>
>However,
>	if(x==5); 
>most certainly is useless, in fact, 
>	if(<<expression>>);  
>is *completely* equivalent to 
>	<<expression>>;
>semantically.  This isn't true for ``while(<<expression>>);'', in general.
>Since this is an obvious abuse of syntax, I would *hope* --
>but not necessarily *expect* -- that lint would catch such an error.  

If you look at pre-processor expanded source, then it is certainly *NOT*
useless.  I have often used code like the following...

:
:
#ifdef DEBUG_ARGS
#   define SHOW_ARG(i) printf( "i is %d\n", (i) )
#else
#   define SHOW_ARG(i)
#endif
:
:
	if( arg_flag )
	    SHOW_ARG( arg );
:
:

which pre-processes into "if(<expr>);" except in the unusual case where
the SHOW_ARGS define is provided to do some debugging on that portion of
the code.  A similar variation is:

:
:
	if ( x_flag )
#ifdef SYSV
	    ; /* SYSV defaults to state x anyhow */
#else
#ifdef BSD
	    do_bsd_x( args );
#else
#ifdef XENIX
	    do_xenix_x( other_args );
#endif
#endif
#endif
:
:

where one porting variation generates an empty then statement.
-- 
"Software and cathedrals are much the same -          | John Macdonald
first we build them, then we pray" (Sam Redwine)      |   jmm@eci386

Horne-Scott@cs.yale.edu (Scott Horne) (07/01/89)

In article <1778@aplcen.apl.jhu.edu>, arrom@aplcen (Ken Arromdee) writes:
>
> if (f1(a)) /* do nothing */ ;
> else if (f2(a)) {
> 	/* some code */
> } else if (f3(a)) {
> 	/* some code */
> } else if (f4(a)) {
> 	/* some code */
> }

We weren't talking about `if(<condition>); else;'; obviously, that usage is
intentional.

					--Scott

Scott Horne                              Hacker-in-Chief, Yale CS Dept Facility
horne@cs.Yale.edu                         ...!{harvard,cmcl2,decvax}!yale!horne
Home: 203 789-0877     SnailMail:  Box 7196 Yale Station, New Haven, CT   06520
Work: 203 432-6428              Summer residence:  175 Dwight St, New Haven, CT
Dare I speak for the amorphous gallimaufry of intellectual thought called Yale?

knudsen@ihlpl.ATT.COM (Knudsen) (07/04/89)

In article <411@isadora.ikp.liu.se>, hacker@isadora.ikp.liu.se (Goran Larsson [Hacker of Hackefors]) writes:
> It's your own fault -- you should have written it as
> 	if ( condition ) {
> 		action;
> 	}
> to reduce the risk of errors!

Yes, but suppose you make the same typo and get
 	if ( condition ); {	/* extra semicolon */
 		action;
 	}

Isn't this still legal C (with the same bug), since compound blocks
may be started anywhere?
I can see always using the { } in case you want to add more statements
later, but I don't see where it avoids the original type bug.
-- 
Mike Knudsen  Bell Labs(AT&T)   att!ihlpl!knudsen  knudsen@ihlpl.att.com
  Round and round the while() loop goes;
  "Whether it stops," Turing says, "no one knows!"
Shotguns -- just say PULL!

bill@twwells.com (T. William Wells) (07/04/89)

In article <11038@ihlpl.ATT.COM> knudsen@ihlpl.ATT.COM (Knudsen) writes:
: Yes, but suppose you make the same typo and get
:       if ( condition ); {     /* extra semicolon */
:               action;
:       }
:
: Isn't this still legal C (with the same bug), since compound blocks
: may be started anywhere?
: I can see always using the { } in case you want to add more statements
: later, but I don't see where it avoids the original type bug.

It avoids the bug because, if you always use braces, putting a
semicolon in that place is just not one of the typos you'll do.
Consider the hand movement necessary to do that and you'll see
what I mean.

---
Bill                    { uunet | novavax | ankh | sunvice } !twwells!bill
bill@twwells.com

Bob.Stout@p6.f506.n106.z1.fidonet.org (Bob Stout) (07/04/89)

In an article of <28 Jun 89 08:32:33 GMT>, Goran Larsson writes:

 >In article <105@borabora.omni.com> bob@omni.com (Bob Weissman) writes:
 >>Last week I spent an entire day tracking down one of those bugs you just
 >>don't see after staring at your code too long.  It was of the form:
 >>
 >>       if (condition);
 >>           action;
 >
 >It's your own fault -- you should have written it as
 >        if ( condition ) {
 >                action;
 >        }
 >to reduce the risk of errors!
 >
 >>My lint (SunOS 4.0.1 version) did not flag the extra semicolon.
 >
 >It isn't supposed to find this "error" as it is legal C.

  Walter Bright offers us PC-C'ers a worthwhile feature in the Zortech C  
preprocessor:

        if (condition);         /* issues a warning     */
        if (condition) ;        /* issues no warning    */

  Although this is of marginal usefulness in `if' statements, it's quite  
useful when using `for' or `while' statements with null operations to simply  
preset an index or to perform some operation which may be contained within the  
body of the `for' statement. 

Bob.Stout@p6.f506.n106.z1.fidonet.org (Bob Stout) (07/04/89)

In an article of <28 Jun 89 15:13:00 GMT>, (Edward J Driscoll) writes:

 >It is legal, but I would hope for a warning from such an obvious
 >semantic error.  I don't use lint much, but Borland TC 2.0 will
 >warn you about some *legal* constructs like "if(x = 5)".  Oddly, I
 >just tried it and it also lets "if(x==5);" get by without a peep.

  See my previous message on the semicolon issue. As to `if (x = 5)', I   
thought most C programmers nowadays always wrote the constant part of a  
logical comparison on the left side as a regular issue of style. Writing
`if (5 = x)' instead would allow the preprocessor to catch your mistake for   
you. 

hacker@isadora.ikp.liu.se (Goran Larsson [Hacker of Hackefors]) (07/05/89)

In article <11038@ihlpl.ATT.COM> knudsen@ihlpl.ATT.COM (Knudsen) writes:
>In article <411@isadora.ikp.liu.se>, hacker@isadora.ikp.liu.se (Goran Larsson [Hacker of Hackefors]) writes:
>> It's your own fault -- you should have written it as
>> 	if ( condition ) {
>> 		action;
>> 	}
>> to reduce the risk of errors!
>Yes, but suppose you make the same typo and get
> 	if ( condition ); {	/* extra semicolon */
> 		action;
> 	}
>Isn't this still legal C (with the same bug), since compound blocks
>may be started anywhere?

The problem is that "if ( condition )" feels like a function call to
your fingers and when your brain orders a new line, one of your fingers
will automagically add the semicolon.  If you add the opening curly
brace before ordering a new line then your fingers will realize that the
semicolon is inapropriate.  Have you ever seen "if ( condition ); {" in
a program?
--

  !       _
  ! !    Goran Larsson  [The Hacker of Hackefors]
--+-!    Hackefors, Linkoping, SWEDEN (See)  +46 13-155535 (Hear)
  !-+--  ...!uunet!sunic!liuida!prodix!isadora!hacker (UUCP)
  ! !    hacker@isadora.ikp.liu.se (Internet)     _
    !

diamond@diamond.csl.sony.junet (Norman Diamond) (07/06/89)

In article <16399.24B11BBE@urchin.fidonet.org> Bob.Stout@p6.f506.n106.z1.fidonet.org (Bob Stout) writes:

>As to `if (x = 5)', I   
>thought most C programmers nowadays always wrote the constant part of a  
>logical comparison on the left side as a regular issue of style.

And what about `if (x = y)' ?

Even when one of those is a constant, sure some PROTECTION is obtained
by reversing the operands, but not STYLE.

--
Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net)
 The above opinions are claimed by your machine's init process (pid 1), after
 being disowned and orphaned.  However, if you see this at Waterloo, Stanford,
 or Anterior, then their administrators must have approved of these opinions.

diamond@diamond.csl.sony.junet (Norman Diamond) (07/06/89)

In article <414@isadora.ikp.liu.se> hacker@isadora.ikp.liu.se (Goran Larsson [Hacker of Hackefors]) writes:

>The problem is that "if ( condition )" feels like a function call to
>your fingers and when your brain orders a new line, one of your fingers
>will automagically add the semicolon.

This is exactly true.  Thank you for a perfect explanation.

/* FLAME directed to certain people NOT INCLUDING Mr. LARSSON

In fact, it is true of many things about C.  Now I understand the
defenders of C.  It isn't the language that encourages programming
errors, it's our fingers.  We should all upgrade our fingers to the
newest bug-free release.

*/

--
Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net)
 The above opinions are claimed by your machine's init process (pid 1), after
 being disowned and orphaned.  However, if you see this at Waterloo, Stanford,
 or Anterior, then their administrators must have approved of these opinions.

gwyn@smoke.BRL.MIL (Doug Gwyn) (07/07/89)

In article <10459@socslgw.csl.sony.JUNET> diamond@csl.sony.junet (Norman Diamond) writes:
>You should not hate C.  You should only hate the people who force us
>to continue using it, 15 years after such defects are known.

C use has spread like wildfire in recent years, and it is improbable that
much of that was due to anyone "forcing" the new C users to use it.  They
may be just "camp followers", or they may have chosen C on its (relative)
merits, or for any of a number of reasons.

I'm personally intimately familiar with C's quirks and deficiencies,
but I still use it for the majority of applications because it fills
its ecological niche much better than any alternative.  I suspect many
other C users have similar reasons.

des@PacBell.COM (Doug Sanderson_Gomke) (07/07/89)

In article <10459@socslgw.csl.sony.JUNET> diamond@csl.sony.junet (Norman Diamond) writes:
>In article <105@borabora.omni.com> bob@omni.com (Bob Weissman) writes:
>
>>Last week I spent an entire day tracking down one of those bugs you just
>>	    action;
>>My lint (SunOS 4.0.1 version) did not flag the extra semicolon.
>>
>>I Hate C.
>
>This is one of many defects in C . . .

I suggest both of you consider the difference between a _bug_ and a
_feature_.  This particular _feature_ of C is one of the things that
adds to its flexibility and therefore its usefulness.  A simple way
to check for the missuse of this feature is to do a global search for
_);_, if you are inclined to typos (as I am). ("It is a poor workman
who blames his tools").
bibi  

mcdaniel@uicsrd.csrd.uiuc.edu (Tim McDaniel) (07/10/89)

In article <10459@socslgw.csl.sony.JUNET> diamond@csl.sony.junet
(Norman Diamond) writes:
> You should only hate the people who force us to continue using C, 15
> years after such defects are known.

I hate it when this sort of thing happens.  To the guy holding the gun
to Norman's head, forcing him to use C: cut it out, will ya?

Seriously, I suppose Norman means that there is no language that
- has a better syntax than C
- has expressive power not much less than C's
- is as portable and commonly supported as C
and that the lack of such a language requires that he use C.

While I too would like to see such a language, I submit that nobody in
particular *owes* it to us.
--
"Let me control a planet's oxygen supply, and I don't care who makes
the laws." - GREAT CTHUHLU'S STARRY WISDOM BAND (via Roger Leroux)
 __
   \         Tim, the Bizarre and Oddly-Dressed Enchanter
    \               mcdaniel@uicsrd.csrd.uiuc.edu
    /\       mcdaniel%uicsrd@{uxc.cso.uiuc.edu,uiuc.csnet}
  _/  \_     {uunet,convex,pur-ee}!uiucuxc!uicsrd!mcdaniel