C's syntax

Alex Martelli aleaxit at yahoo.com
Tue Oct 24 06:17:24 EDT 2000


"Erik Max Francis" <max at alcyone.com> wrote in message
news:39F4FEAF.FA466927 at alcyone.com...
    [snip]
> > Visual C++ may not be "reasonable", but it's still one of the most
> > widespread on the market, and does NOT give this warning at normal
> > warning-levels (and the system header files spew oodles & oodles of
> > warnings if you try to enable warnins at pedantic-level, so one
> > does not normally use that).
>
> One should never be running at the default warning level.  One should be
> turning as many warnings on as one can stand.

...because C is full of trip-wires just waiting for your foot.  Yes,
I agree -- I also think that one of the best books ever on C was
Koenig's "C Traps and Pitfalls", exactly because it concentrated on
the many, MANY ways C can trip you up (many of them related to its
tortured syntax, though, of course, not all) and the good habits
you should acquire to ameliorate the situation a bit.

I fully agree with Koenig (a great programmer, and a great expert
in C, and later C++, by the way) that "Even C experts come across
problems that require days of debugging to fix" (from the preface
of his book, cfr the URL
    http://www.research.att.com/~ark/bibliography/pitfalls.html).

"if(a=0)" is not one of them (once you're experienced, you'll
find the error in far less than 'days'), but there is no reason
to go looking for it, any more than there is to use "intervals
with bounds included" in loops, rather than the far less error
prone idiom of "lowerbound included, upperbound excluded" which
Koenig first proposed in this book.  [Python's range() builtin,
its sequence-slices, etc, work on said idiom too, by the way;
_that_ one is not C-specific!-)]

But, as I said, you just can't turn the warning level up all
the way (to /W4) with Visual C++, if you have any system
headers -- you'll get swamped with warnings about constructs
being non-portable (of course system headers DO include many
non-portable constructs...!-).  The default /W3 is pretty
strict... but it does NOT warn of "if(a=0)".


> > It's a good coding habit to get into, to ensure that particular
> > slip will be caught by any standard compiler, rather than relying
> > on specific warning-relater features that NOT all compilers have.
>
> It is largely unnecessary.  It is a novice programming error, one that
> actual programmers do not make unless they are very green.  Given that
> any reasonable compiler will warn about such constructs, making a major
> change in style for an error that advanced programmers do not make is
> overkill, to say the least.

Koenig wrote his landmark book with about a decade's worth of C
experience (one could hardly have more back then, since that was
about the language's age inside Bell Labs:-), and he disagreed
with you, recommending the "if(0==a)" idiom.  And why not?  One
may as well get used to the idioms that are most effective in the
language one is using -- taking advantage of humans' already
mentioned ability to grow used to anything, after all.  Keeping
the constant on the left rather than on the right has absolutely
no bad side-effects.  (using "if(!a)" may be an even better style
for this specific case, but there remain "if(1==a)" and so on:-).

"actual programmers" DO make typos all of the time -- else why
would you recommend keeping warnings as severe as possible, or
think that "if(a=b)" will be warned against by "any sensible
compiler"?!  A language with good syntax will, among other things,
tend to have common typos produce compile-time-errors.  But when
the syntax is NOT good, every little bit spent avoiding its traps
and pitfalls helps.  Of course, this little idiom is no panacea,
but, besides constants, it helps distinguish at a glance two very
similar, common, and semantically different idioms:
    while(a=nextitem()) ...
i.e., loop copying each next-item to variable a (to be used in
the loop-body) and exit when next-item returns 0; and
    while(nextitem()==a) ...
i.e., loop _comparing_ each next-item to variable a, and exit
when a next-item is observed that _differs_ from a.

"gcc-witout-warnings" syntax forces you to write the first case
with doubled-parentheses, but that is not what C syntax says.
So, for generality, it's much better to get used to write the
second case with the function-call on the left of the comparison
operator.  Nothing (except switching to a language with better
syntax!-) will really protect you from the specific typo:
    while((a==nextitem()) ...
where you MEANT to assign-to-a (as suggested -- to the human
reader knowledgeable of such things -- by the doubled parentheses)
but are in fact *comparing*-to-a instead since a 'keyboard
stutter' ended up doubling the equal-sign...


Alex






More information about the Python-list mailing list