Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!alice!research!dmr From: dmr@research.UUCP Newsgroups: net.lang.c Subject: X3J11 thoughts Message-ID: <1036@research.UUCP> Date: Mon, 23-Jul-84 01:10:35 EDT Article-I.D.: research.1036 Posted: Mon Jul 23 01:10:35 1984 Date-Received: Mon, 23-Jul-84 06:32:59 EDT Lines: 166 A few comments on issues raised in net.lang.c. (I do read it). First, I am in general pleased with the work of the X3J11 ANSI committee, and am especially content that they are now the ones who have to worry about the kinds of questions raised in this group, and that I don't have to rewrite the manual. Henry Spencer's summary of Larry Rosler's Usenix presentation on the current state of things was excellent. I have only one serious qualm about the way things are preceding in X3J11: it concerns argument declarations in function declarations. This is the only important change in the language as usually implemented. Let's concede that this should have been done long ago; the only interesting question is whether it is useful to do it now. Recognizing that it was not practical to demand that all existing programs be changed to declare function arguments, the committee leans to allowing declarations but not requiring them. For example: OLD NEW extern double sin(); extern double sin(double); ... ... main() { main() { double x = sin(1); double x = sin(1); } } In the new version the argument of sin will be coerced to double. In the old version (still legal syntactically) there is no such coercion, the program is just wrong. Lint will tell you so, but not everyone uses lint, and not everyone even has it. The problem is that because both programs will be accepted by most new compilers, there is ample opportunity for confusion. Thus, users of new compilers will soon come to have include files that nicely declare the arguments of sin() and other functions, and to depend on the coercions. Often their programs will appear to compile properly under old compilers, but won't work. The other problem with the proposal is that by allowing a mixture of the old and new syntax, the compiler can't be sure whether actual arguments were were declared and coerced at all call sites; this cuts off some useful optimizations. For example, the float->double widening in arguments is very costly if you use a software implementation of IEEE floating point. If the compiler could be absolutely sure that each caller knew that a function argument was declared float everywhere, it wouldn't have to convert. The committee had three choices: 1) Leaving things alone, with a subchoice of allowing argument declarations for checking purposes (no coercion); 2) The proposed scheme; 3) Requiring functions to be fully declared including all arguments (like Pascal, A68, indeed all other modern languages in which the question comes up). Choice 1 with advisory declarations is not worth the trouble. Leaving things completely alone was quite possible. We managed to muddle along so far. Choice 3 is in an obvious way the correct one. It has some costs in complexity (see below). The only problem is that it is utterly impractical because it breaks every C program in existence. Choice 2's problem is that it is neither fish nor fowl; it trips on the same technical complexities of variable argument lists encountered by choice 3 and complicates the language (e.g. "int f(void)" had to be invented to make it work). Rather than clearly stating that getting argument types right is the programmer's responsibility (as with 1) or that a mandatory previous declaration will coerce and check the actual arguments (as with 3), it leaves everyone somewhat confused as to what will happen at any particular call. All in all, I have to think that 3 is best but impossible, and that 1 is marginally better than 2. Supporters of 2 are secretly hoping to be able to go for 3 in the future. Unfortunately, I suspect that instead of having either 1 or 3 forever we will have a mishmash forever. Appendix B of the current draft says that the compiler is entitled to warn you if "a function is called but no prototype has been supplied"; this still seems to let you say extern double sin(); ... sin(1); with no warning. Variable argument lists: One of the problems you get into when argument types are supposed to be known in advance, and even when they're not, is what to say about the printf family in the language description. The old manual said that actual arguments (after some widening) had to agree in type and number with formals. Unstated, but implicit in all implementations, was that somehow printf had to work. I don't know of any way to formalize this in the context of C. A good side effect of having syntax to notify the compiler that a function has an unknown number and type of argument is that everyone is on notice that something funny is going on. A bad effect is that programmers will come to believe that such things are in any way portable. They are not. Unless someone comes up with a brilliant invention, neither ANSI nor I will promise anything in writing. Suppliers of C compilers and libraries are responsible for making printf work. Users can't expect to do it themselves reliably. Macros like va_args (which came from BTL, not Berkeley) improve things in practice, and can often make variable-argument functions more exportable. What you will not get is a description of the complete semantics. It's just too machine dependent. Open-ended structures: Someone else asked about structure declarations with things like char x[1]; at the end, where the intent is to have a fixed header with variable stuff tacked on at the end. Once again, you are not likely to find a discussion of this in a C reference manual. Writers of language descriptions (even me) like to have a firm idea of what various declarations of objects mean and what operations can be performed on the objects. Unless people have a good alternative to unions or PL/I's iSUB or a better idea please don't ask for formal blessing on this. Enums: Was this the place I grossed out at Usenix? I did say "botch." In the current proposed standard, enum types are ints and there is no restriction on their use, except that Appendix B says that a compiler may warn you if you assign something to an enum variable except a value of that enum type. This is very close to my original design. The choice with enums (as has been reported) was between 1) making them a neater way of specifying integer constants 2) making each a unique type as in Pascal I decided against the second choice because to make them useful would have required larger language changes than I was prepared for (arrays indexed by enum values, arithmetic on sparse values, that sort of thing). I proceeded to put enums as integers into the PDP-11 compiler, while publicly worrying about the choice, and saying that it might be nice if lint warned about implausible enum assignments. At just that instant the Sys III compiler was being completed, the same program that took a trip to California to become the BSD compiler. And unfortunately, it incorporated halfway thoughts about what enums should be. (So did the the manual; it said that enums were a unique type but also were ints). Let it be recorded that earlier Sys III and BSD compilers are buggy and incorporate no useful realization of enums. typeof: is a good deal. Write the committee. Grace Hopper: I think Kuenning meant Jean Sammet. How to complain: If you feel strongly about something in the standard, it is advisable to write to the committee instead of grousing here. Some of them read this group, but I doubt if they save the submissions away and take them to meetings. Try a real, paper letter. Pick one of Larry Rosler Room 1337 AT&T Bell Laboratories 190 River Rd. Summit NJ 07901 X3 Secretariat: CBEMA Suite 500 311 First St NW Washington DC 20001 Letters to X3 should probably refer prominently to X3J11. Suggestions should be specific and to the point. Dennis Ritchie