X3J11 thoughts

dmr at research.UUCP dmr at research.UUCP
Mon Jul 23 15:10:35 AEST 1984


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



More information about the Comp.lang.c mailing list