problems/risks due to programming language

Richard O'keefe ok at goanna.oz.au
Fri Feb 23 20:26:04 AEST 1990


In article <4582 at jarthur.Claremont.EDU>, jseidman at jarthur.Claremont.EDU (James Seidman) writes:
: In article <2903 at goanna.oz.au> ok at goanna.oz.au (Richard O'keefe) writes:
: >One debatable feature about "break" is that it is not automatically
: >implied at the end of every case.  That means that you can leave it
: >out when you didn't mean to.  There are several ways of dealing
: >with the problem...
: 
: It's interesting how this goes from a "debatable feature" to a "problem" in
: three sentences.

It's interesting how many people have difficulty reading English.
"the problem" refers to "leaving a break out when you didn't mean to",
not to the break statement as such.

Let me say this one more time in words that have but one sound in them
save for the text which I quote from my last:

	If you want a case in C to stand on its own and not fall through
	to the next case, you must write the 'break' sign, not C, for C
	deems it the norm for a case to fall through to the next save
	when you make it quite clear that you do not want this.
	[*this* is the "debatable feature"]
	To the woe of a great host of those who write in C, what C deems
	the norm is rare, and oft we slip and leave the 'break' sign out.
	We get a text which C likes well, which does not do what we want,
	but where it is hard to see what we did wrong.
	[*this* is the "problem"]

	WE DO NOT NEED TO CHANGE C TO SHUN THE SNARE;
	we have but to add to the tools we use to write C.

Now, why did a *positive* claim about C, a suggestion that C isn't
badly enough broken to warrant fixing, elicit an attack?


: This argument seems to me about equivalent to saying "One
: of the debatable features about 'if' is that a new program block is not
: defined.  That means that you can have a statement which you meant to have
: in the if statement but isn't."  You know, something like
:   if (a == b)
: 	bar(a);
: 	foo(a);
:   a++;
: Do you propose making an editor macro to handle ifs to prevent this?

Some sort of tool YES.  And such a tool exists.  It's called "indent".
I don't have this problem, because I use
	if (test) stmt-on-same-line;
if it's a single statement which will fit on the same line, or
	if (test) {
	    stuff that won't fit on one line
	}
otherwise, so the mistake can't happen.  But I find that it _always_
pays me to run indent on other peoples' code precisely to catch this
kind of mistake.  I've met people with an editor key bound to
	insert "if () {"
	insert a new line at the same indentation level
	insert "}"
	go back to just after the "("

: The fact that some people have trouble
: remembering to put a "break" in the right place isn't a problem with the
: language, it's a problem with the programmer.

If a few people had the problem, it would be a problem with them.
When a LOT of people have the problem, it's a problem with the language.
My attitude is that saying "C is perfect" is just as futile as saying
"I wish C were exactly the way I'd like it", and that what we should be
doing in this newsgroup is suggesting ways of reducing known risks.
For example, I posted a tool a year or two ago for finding comments that
go on longer than you expected (it just copies the file to the terminal,
displaying comments highlighted).

: According to K&R (2nd ed.), "A break causes the innermost enclosing loop or
: switch to be exited immediately." (p. 64) 

So?  We all knew that.  

: {an example of a for inside a switch deleted}
: I haven't compiled this particular example, but I have done things
: like this many times with Turbo-C, MS-DOS msc 5.0, gcc, and BSD 4.2 cc.  I
: don't know what platform you're running that has such a nonstandard form of
: C that it doesn't work like this.

What on earth are you on about?  What I wrote was that I have run into
trouble with a switch inside a loop (not a loop inside a switch) where
I wanted to exit the loop but the switch captured the break.  I'm not
talking about any nonstandard C, but the simple fact that 

	for (...) {
	    switch (...) {
		case...
		    ...
			/* now I want to exit the LOOP */
				
(a) can't be done without introducing a goto or return, or rewriting
    the code.
(b) is risky because if you put a 'break' there _thinking_ it will
    terminate the loop the compiler will happily accept it but do
    something else (this is particularly risky when you turn an
    existing 'if' into a 'switch')

: I don't see why you think there need to be two separate functions to do the
: same thing.

I don't.  Heck, 'goto' will do the job just fine.  The point I raised
is that the grandparent of C *DID NOT HAVE THIS PROBLEM*.  It's not a
risk which was introduced into C because the designers didn't happen to
think of it.  In BCPL it is perfectly safe to turn an 'if' into a
'switch' because BREAK statements continue to refer to the same loop
that they referred to before, cases must be ended with ENDCASE.


: The behavior [of break] is unambiguous and consistent.

Indeed and it is.  It is also confusing and risky.
To cite an example from another programming language, the "cut"
operation in Prolog is unambiguous and consistent and from one point
of view does a single thing.  It is also notoriously a source of
confusion and error.

I stand by my suggestions that
    - if you have trouble with forgetting 'break' in switches,
      consider writing an editor macro to insert the 'break' with
      the 'case'
    - a tool that checks for missing 'break's would be useful; a
      lint option would be ideal but
	cc -E prog.c | {check for "case" or "default" not preceded
	by "{", ":", "return ...;" or "break;"}
      might be useful.
and my question
    - given that BCPL separated "quit a case" (ENDCASE) from
      "leave a loop" (BREAK), why did C conflate them?



More information about the Comp.lang.c mailing list