Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!samsung!munnari.oz.au!goanna!ok From: ok@goanna.oz.au (Richard O'keefe) Newsgroups: comp.lang.c Subject: Re: problems/risks due to programming language Message-ID: <2905@goanna.oz.au> Date: 23 Feb 90 09:26:04 GMT References: <1597@awdprime.UUCP> <8133@hubcap.clemson.edu> <2903@goanna.oz.au> <4582@jarthur.Claremont.EDU> Organization: Comp Sci, RMIT, Melbourne, Australia Lines: 133 In article <4582@jarthur.Claremont.EDU>, jseidman@jarthur.Claremont.EDU (James Seidman) writes: : In article <2903@goanna.oz.au> ok@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?