An Assessment of C
C is a compact, efficient, and expressive language. Indeed, C is good enough that it has almost completely supplanted the use of assembly language programming on many systems. The use of a clean, readable high-Ievel language has overwhelming advantages; one is simply that it becomes possible to read programs, which is excruciatingly difficult in some languages.
C is a relatively "low level" language. This characterization is not pejorative; it simply means that C deals with the same sorts of objects that most computers do namely, characters, numbers, and addresses. These can be combined and moved about with the arithmetic and logical operators implemented by real machines.
Since C is relatively small, it can be described in a small space and learned quickly. You can reasonably expect to know and understand and, indeed, regularly use the entire language.
Another advantage is its portability. Although C matches the capabilities of many computers, it is independent of any particular machine architecture. With a little care, it's easy to write portable programs that can be run without change on a variety of machines. The standard makes portability issues explicit and prescribes a set of constants that characterize the machine on which the program is run.
Another of C's strengths is its absence of restrictions. A popular trend in programming languages is "strong typing," which (roughly speaking) implies that the language undertakes to check carefully that the program contains only valid combinations of data types. Strong typing sometimes catches bugs early, but it also means that some programs just can't be written, because they inherently require violations of the type-combination rules.
A storage allocator is a good example: You can't write Pascal's new function which returns a pointer to a block of storage in Pascal, because there's no way to define a function that can return an arbitrary type. But it's easy and safe to write it in C because the language lets you state that a specific violation of the type rules is intentional.
C is not a strongly typed language, but as it has evolved, its type checking has been strengthened. The original definition of C frowned on, but permitted, the interchange of pointers and integers; this has long since been eliminated, and the standard now requires the proper declarations and explicit conversions that good compilers had already enforced. The new function declarations are another step in this direction. Compilers will warn of most type errors, and there is no automatic conversion of incompatible data types. Nevertheless, C retains the basic philosophy that programmers know what they are doing; it only requires that you state your intentions explicitly.
C has even proven to be a good language for other languages to compile into. One of the best examples is the Yacc-compiler compiler, which converts the grammar specification for a language into a C program that is used to parse statements in that language. Naturally, one language specified this way is C itself.
What's wrong with C? At the lowest level, there are some poor choices of operator precedences. Some users feel that the swi tch statement should be changed so that control doesn't flow through from one case to the next, as it does now. The concise syntax is sometimes daunting to newcomers; complicated declarations are often hard to read. One of the new examples in the second edition of The C Progromming Language is a pair of programs to convert C declarations into words and back again.
Portability problems sometimes arise if you rely on undefined or implementation-defined properties. For example, the order in which function arguments are evaluated is not specified, so it's possible to write code that depends on that order and will thus execute differently on different machines. This is not a grave problem, since it's easy to detect the dependency, but people still overlook it from time to time, with unfortunate effects.
Over the past decade, C has evolved, although the rate of change has been slow. The ANSI standard formalizes these changes and adds a few of its own. There has been a steady increase in the amount of error-checking by the compilers: Although there are still few restrictions on what you can say, you now need to be more explicit when you're doing something strange.
Where is C likely to go in the next few years? The most likely evolution is to continue this slow but steady improvement, with new features added cautiously. Caution is necessary simply because of the importance of maintaining compatibility with the huge body of C code already in use. Changes cannot be made gratuitously.
Realistically, C itself isn't likely to change to a major degree; rather, new languages will come from it. One example is C++, which provides facilities for data abstraction and object-oriented programming while remaining almost completely compatible with C (see "A Better C?"). In the meantime, C wears well as your experience with it grows. With 15 years of C experience, we still feel that way.
Kernighan, Brian W., and Dennis M. Ritchie. The C Programming Language. 1st ed. Eng1ewood Cliffs, NJ: Prentice-Hall, 1978. This is the standard reference on C.
Kernighan, Brian W., and Dennis M. Ritchie. The C Programming Language. 2nd ed. Englewood Cliffs, NJ: Prentice-Hall, 1988. This edition describes ANSI C.
Stroustrup, Bjarne. The C++ Programming Language. Reading, MA: Addison-Wesley, 1986.
Editor's note: Adapted with permission from Potentials. December 1983, pages 26-30. Copyright 1983 IEEE.