Previous Table of Contents Next


6.2.4.3. Static Type Checking

I have no recollection of discussions, no design notes, and no recollection of any implementation problems with the introduction of static (strong) type checking into C with Classes. The C with Classes syntax and rules, the ones subsequently adopted for the ANSI C standard, simply appeared fully formed in the first C with Classes implementation. After that, a minor series of experiments led to the current (stricter) C++ rules. Static type checking was to me, after my experience with Simula and Algol68, a simple must, and the only question was exactly how it was to be added.

To avoid breaking C code, it was decided to allow the call of an undeclared function and not perform type checking on such undeclared functions. This was of course a major hole in the type system and several attempts were made to decrease its importance as the major source of programming errors before finally—in C++—the hole was closed by making a call of an undeclared function illegal. One simple observation defeated all attempts to compromise and thus maintain a greater degree of C compatibility: As programmers learned C with Classes, they lost the ability to find runtime errors caused by simple type errors. Having come to rely on the type checking and type conversion provided by C with Classes or C++, they lost the ability to quickly find the silly errors that creep into C programs through the lack of checking. Further, they failed to take the precautions against such silly errors that good C programmers take as a matter of course. After all, “such errors don’t happen in C with Classes.” Thus, as the frequency of runtime errors caused by uncaught argument type errors goes down, their seriousness and the time needed to find them goes up. The result was seriously annoyed programmers demanding further tightening of the type system.

The most interesting experiment with “incomplete static checking” was the technique of allowing calls of undeclared functions but noting the type of the arguments used so that a consistency check could be done when further calls were seen. Many years later, when Walter Bright independently discovered this trick, he named it “autoprototyping,” using the ANSI C term prototype for a function declaration. The experience was that autoprototyping caught many errors and initially increased a programmer’s confidence in the type system. However, because consistent errors and errors in a function called only once in a compilation were not caught, autoprototyping ultimately destroyed programmer confidence in the type checker and induced a sense of paranoia even worse than I have seen in C or BCPL programmers.

C with Classes introduced the notation f(void) for a function f that takes no arguments as a contrast to f() that in C declares a function that can take any number of arguments of any type without any type check. My users soon convinced me, however, that the f(void) notation wasn’t very elegant and that having functions declared f() accept arguments wasn’t very intuitive. Consequently, the result of the experiment was to have f() mean a function f that takes no arguments, as any novice would expect. It took support from both Doug McIlroy and Dennis Ritchie for me to build up courage to make this break from C. Only after they used the word abomination about f(void) did I dare give f() the obvious meaning. However, to this day, C’s type rules are much more lax than C++’s and any use of f() as a function declaration is incompatible between the two languages.

Another early attempt to tighten C with Classes’s type rules was to disallow “information destroying” implicit conversions. Like others, I had been badly bitten by implicit long to int and int to char conversions. I decided to try to ban all implicit conversions that were not value preserving—that is, to require an explicit conversion operator wherever a larger object was stored into a smaller. The experiment failed miserably. Every C program I looked at contained large numbers of assignments of int variables to char variables. Naturally, because these were working programs, most of these assignments were perfectly safe. That is, either the value was small enough not to become truncated or the truncation was expected or at least harmless in that particular context. There was no willingness in the C with Classes community to make such a break from C. I’m still looking for ways to compensate for these problems.


Previous Table of Contents Next