pmk@craycos.com (Peter Klausler) (03/23/90)
>> Unrestrained pointers are the data structures equivalent of >> uncontrolled GOTOs. A language like C that lets you do anything >> in the world that you please with pointers is very similar to a >> language like BASIC that lets you arbitrarily jump to anyplace you >> want to in your code. >C *is* a language that allows you to jump anywhere you want in your code. >By using longjmp and goto you have nearly as much freedom as you do in >Basic (or, more, assembler). If only you could assign gotos, it'd be >perfect [1]. Think of it as a very portable very high-level assembler [2]. It's this kind of freedom of expression, though, that severely constricts many analyses an optimizing compiler must perform. Setjmp is particularly messy, since it allows flow of control in a function that isn't explicit. As an example, consider: #include <setjmp.h> f (void) { jmp_buf jb; if (setjmp (jb)) /*1*/ goto dijkstra; while (1) g (); j (); /*2*/ dijkstra: ; } Ordinarily, I could throw line /*2*/ away, since there's no normal flow of control in f() that could arrive there. In order to process this program correctly, my compiler needs to know that setjmp() is special, and assume that control-flow arcs exist from every other function call to the point of return from setjmp at /*1*/. This yields a very messy flow-graph and prevents common optimizing transformations. The ANSI C standard attempts to simplify the situation with its proviso that only volatile objects will survive a longjmp, but this doesn't help much in the case of flow-graph construction, and volatile variables completely cripple optimization anyway. Fortran has similar problems, with its ASSIGN and assigned GOTO statements, but the '78 standard has nice rules that restrict ASSIGNs to scalar variables, and prohibit the copying of ASSIGNed variables to one another. Although we must assume flow-of-control from each assigned GOTO to every ASSIGNed label, this tends to be less messy. The programmer even has the ability to restrict the range of potential targets of the GOTO. I'm not saying the Fortran is superior to C in any aesthetic sense (sheath your swords), but it's sure nicer to optimize and parallelize. This is just one example, and not a particularly good one, since ASSIGNs and setjmps are pretty rare; pointer arguments and their aliasing problems are nastier by far. So, if you're using an optimizing compiler, keep your setjmp calls out of time-critical routines; we'll both be happier. -Peter Klausler, writing compilers at Cray Computer Corp. in Colorado Springs
pmk@craycos.com (Peter Klausler) (03/23/90)
OOPS! My C code example in a previous posting was quite incorrect; the call to j() is dead in f() irrespective of the presence of the setjmp. SORRY! What I MEANT to show was that the presence of setjmp()s and function calls in a C function implies flow-of-control that isn't explicit in the syntax of the program. But my example in which this could cause problems in an optimizer was wrong. My apologies to all confused by this. -Peter Klausler @ Cray Computer
jamiller@hpcupt1.HP.COM (Jim Miller) (03/24/90)
>Which is a quite reasonable argument. Pointer-safe languages generally >require garbage-collected heaps, which means size. So I can see that >a language like C which is required to run on Machines With Tiny >Brains will not be "safe" in that respect. > >But, this leaves two issues open: (i) why C has such an idiotic >syntax, arbitrary type-checking, lax compile-time checks and so on, >and (ii) why people think that C's features provide "power" in >general-purpose programming. Point (i) is an accident of history. >Point (ii) still intrigues me. > > Nick. IMHO, IMHO, IMHO, . . . ("~>" means "approximately said") ~>(i) why C has such: ~> 1) idiotic syntax in general, I don't think it does (IMHO). If you are regarding the crypticness, then I think it is less cryptic than APL, and a whole lot more useful than most of the alternatives. I really love "+=" and "++". Some "problems" (my favorites are "==" and switch's "break"), but in the whole I'm a C lover (but don't tell by wife, pardon, significant other). ~> 2) arbitrary type-checking Ok, Ok, I think that lint should to a better job. Especially with typedefs. ~> 3) lax compile-time checks I define the compiler as "cc" + "lint". If you want checks, use lint, if you want code, use cc. Among other things, this makes cc FAST. It is not unusual for all the code on a machine to be re-make'd overnight when a new version of the OS comes out (at least we had to do it sometimes with BSD). With most languages it might have been a week long effort. I know of customers which *will not* recompile, due to the impact on the time their operation -- one just better find a better way. They are not using C. ~> 4) and so on. ~>(ii) why people think that C's features provide "power" IMHO, C is not a high level language, but a powerful, & semi portable, assembler. With C one can usually get more direct access to OS and machine features than are available with most alternates. Speed freaks like having a good understanding of the code that is emitted, and C seems to fit the bill better than many other languages, though this statement could easily start a religious war (nix nix IMHO IMHO) jim - i'm not even sure these are my opinions - miller