problems/risks due to programming language

What`s in a name? misu_ss at uhura.cc.rochester.edu
Tue Feb 27 05:48:28 AEST 1990


In article <806 at enea.se> sommar at enea.se (Erland Sommarskog) writes:
>Scott MacHaffie (machaffi at fred.cs.washington.edu.cs.washington.edu) writes:
>)Bill Wolfe (billwolf%hazel.cs.clemson.edu at hubcap.clemson.edu) writes:
>))   the NEXT case.  In other words, C requires the programmer to use a
>))   dangerous construct on a routine basis.

>))	[stuff deleted]

>))   code associated with the else part.  Thus, we have an inconsistency
>))   in C's design: with one flow-of-control construct (the switch), it is
>))   necessary to use a dangerous GOTO to achieve normal processing, whereas
>)
>)No, it is necessary to use a statement to indicate that the current case
>)statement is finished...like an "end case" or the next "when =) " in ADA.
>
>I don't speak C, so I might have missunderstood something, but I'm
>under the impression that you may exclude the "break" statement
>achieving the effect that you execute the code for the next case too.
>Sometimes possibly a nifty feature, but it seems to me that is a good
>source of errors. Whether it's called "break" or "end case" has no
>importance. You may inadvertantly forget it in both cases.
>

Yupper.  To quote the Holy Scriptures:

"Falling through cases is a mixed blessing.  On the positive side, it allows
several cases to be attached to a single action... But it also implies that
normally each case must end with a break to prevent falling through to the
next.  Falling through from one case to another is not robust, being prone
to disintegration when the program is modified.  With the exception of
multiple labels for a single computation, fall-throughs should be used
sparingly and commented.
	"As a matter of good form, put a break after the last case even
thought it is logically unnecessary.  Some day when another case gets added
at the end, this bit of defensive programming will save you." (K&R p.59)

So, yes I'll agree this is a slight flaw in the case statement, but I'm not
sure I buy all this garbage about "break" being a "dangerous construct."

There has been a war on GOTO constructs for some time and while it certainly
began with reason (remember BASIC without labels???:-)), it gets to the
point where efficiency is not saved.  One really must go to great lengths to
program anything significant without some sort of flow control, which at the
machine level breaks down into conditional or unconditional jumping... (Yes,
a GOTO (EEEEEEKKKKK!!!!)).  

So, we want to be reasonable in our jumps, giving them certain well defined
conditions and having only certain types.  So we *do* indeed, for the most
part want to get rid of the monstrosity known as "GOTO label" (To say
nothing of the kind of line I could write in TRS-80 basic: 
    
     20 IF X OR 2 100 /* This jumps to line 100 if the 2 bit is set in X */
).

In fact I would argue that all GOTO like constructs should be conditional
and local.  And so they are (almost) in C.  For, while, switch, do... -- all
local, and all conditional except one:  break (Yeah, C has goto but everyone
knows never to use *that*).  But break is rather well defined in C.  It exits
from the innermost for, while, do or switch statement.  It goes to an easily
noticeable place near it in the code, unlike goto (let's go label hunting!).
Now I could argue that making the break statement conditional i.e. :

break(expression);  performs break if expression is true, nothing if false.

would be a good idea.  For one thing certain loop breaking would be easier
to write.  Admittedly the common uses in switch statements would require
three extra characters...  I don't think it's a big enough deal to be worth
changing.  Break simply isn't that dangerous.  I'm not so sure GOTO is all
that dangerous if treated with the proper respect (But then I've done
assembly programming...:-)). 

Arguments for the break statement:  Do you ever want to break out of a
while, for or do construct?  ("Oh, no!" I hear some say, "Properly written
programs *never* need do that."  My answer:  Yes, you are right and BTW,
every reasonable language is Turing Equivalent -- go program on a turing
machine.) The only option without some kind of break statement, is to use
flag variables and a couple of extra conditionals (Quoth my algorithms
professor, "Flag variables are as ugly as gotos, but they can't be helped in
Standard Pascal...").  

Thing is, lot's of things are pretty dangerous in programming languages but
these things can be very useful.  Noone in their right mind can claim that
pointer manipulation is any less dangerous than a flat out goto label
statement (IMNSHO, it's tremendously more dangerous), but would any
reasonable programmer trade it for the world?  There is simply too much that
becomes easy and elegant when you use pointers into real memory instead of
having to create your own integer index pointers into arrays simulating
memory in order to implement, say, a tree.  We did this in my algorithms
class, in order to learn about how pointers are implemented.  It's not that
hard, just painful and complicated.  I'll take pointers any day of the
week.  

I'm saying that we need not be quite so anal-retentive about the constructs
we allow in programming languages.  Admittedly, C is not for the faint of
heart, and I'll be surprised if it catches on in the big business world.
There is too much need for programming and not enough programmers who can
handle a C environment.  That's ok by me -- I'm really not interested in
that sort of dp anyway (although the poor saps ought to get something better
than C*BOL to use).  But the one thing that makes C more dangerous, more hairy,
more able to strike fear into the heart of the novice programmer than even
the demonic teenage Mike S. with his TRS-80 model III spaghetti basic
interpreter using Machine Language subroutines left and right, is C's use of
pointers and operators.  Not the silly break statement or some small
weakness in the switch.  

C pointers and operators, while hairy, are extremely elegant.  This is why
so many people like to program in C.  But admit it, they are not trivial to
understand.  So my main point is this:  

Anyone who has any business programming in C, should be able to handle a
switch statement where cases fall through.  

And it's true, every C programmer gets steeped in the heritage of the
switch.  Why the third commandment of C states quite clearly:

"Thou shalt put a break statement at the end of each case in a switch, even
unto the last in which it is not logically necessary."

So what's the problem?  If you feel so strongly about a switch statement
than you are obviously of a different school than C'ers.  

There are two main schools of looking at language implementation.  One,
typified by Standard Pascal, says that the programmer probably doesn't know
what s/he is doing and that a language should not let him/her do anything
even slightly out of the ordinary.  The second, typified by C, says that the
programmer knows or should know what s/he is doing and so "I'll just do what
s/he tells me as long as I understand what s/he is saying."  If you are a
type I programmer, using C must feel like walking a tightrope between the
towers of the world trade center.  If you are a type II programmer, using SP
is like trying to answer the four-year-old who has learned how to ask, "Why?"

The best languages are obviously not going to go whole hog in either
direction, but in general you should use what you feel comfortable with.  I
like C, You like Ada, so use what you like.  I think K&R made a reasonable
choice with break.  I like being able to fall through a switch, even if I
have to take a little care with it.  Do you think I type *anything* in C
without taking a certain amount of care?  

							--mike


-- 
Mic3hael Sullivan,                    Society for the Incurably Pompous
		     		-*-*-*-*- 
"In the usual way":  That's a phrase that mathematicians use to let you know
they're smarter than you are.				--Norman Stein



More information about the Comp.lang.c mailing list