Previous Table of Contents Next


The most important problem with this condensed coding style is that, when you're reading volumes of code, it's easy to overlook statements where the ++ increment has been placed on the wrong end of the index identifier. The following alternatives use the code's visual layout to show the critical sequence of operations:

++top;
array[top] = item;
array[next] = item;
++next;

These alternatives also eliminate the need to use post increment (and post decrement) operations, removing one more piece of syntactic clutter and a potential source of coding errors from the program. Note also that the two-statement alternatives are just as easy to write and, with most optimizing C compilers, will execute as fast as the one-statement approach.

To most people, even non-C programmers, the difference in clarity in these isolated one- or two-line examples is small. However, in large programs or more complex statements, the differences mount up. As the examples in the rest of this book point out, conventional C style — much of it based on assembly language programming techniques — can also lead to subtle, but fatal, program errors.

A Better C

Many claims have been made for C++, but one thing seems certain: C++ is a "better" — if more complex — version of C. C++ adds some important language features missing in C; for example, reference parameters, inline functions, and templates to define generic functions and classes. These features aid clearer programming and can reduce — but not eliminate — the need for macros in C++ programs.

What C++ doesn't do is eliminate any of C's traps. C++ was intentionally designed to be an almost complete superset of C; that is, almost any ANSI C program — even one using dangerous C techniques that have better alternatives in C++ — will compile as a C++ program. Thus, you can still be burned by typing = instead of == in a C++ program (I discuss this in Chapter 2). C++ also continues the heavy use of special characters, rather than keywords, in its syntax. The problems that arise from C's use of * for "pointer" or "contents of" and & for "address of" are compounded by new C++ notations, such as a trailing & for "reference."

C++ also introduces facilities for object-oriented programming (OOP). The primary new C++ concept is the "class," which is a facility to package functions and variable declarations together so that new data types can be defined and used in C++ programs. C++ also provides for "inheritance," a facility for deriving a new class definition from an existing class. The OOP capabilities of C++ are quite powerful, and when you work with a well-designed C++ class library, many implementation details can safely be ignored. But creating new classes is a different matter; and, if you write many non-trivial programs in C++, eventually you'll have to construct some of your own classes. As Chapter 8 points out, there are some very slippery slopes to climb as you write C++ classes.

The question frequently arises of whether a programmer who doesn't know either C or C++ should learn C or C++ first. That's a hard call, and the best answer may be to learn one of the object-oriented extensions of Pascal or Smalltalk first, the idea being to learn the OOP concepts with a language not so laden with assembly language baggage, then learn how to do it in C++. In any case, you can't completely skip over learning about problem areas in C because most of these still exist in C++. As a result, much of this book is directed at problem areas common to both languages.

Conquering C

To pick the right projects for C or C++, and then use the language effectively, you have to ignore a lot of conventional attitudes towards C and C programming practices. Many of these attitudes and practices are rooted in a time and place 15 years ago when C was a major step forward for systems programmers. Today there are good alternatives to C for many applications, and programming practices have changed considerably. One of the most important differences between 15 years ago and today is that businesses are placing much more emphasis on controlling software development costs than on modest improvements in performance. Thus, developers trying to control costs want to avoid language features such as address pointers and coding practices such as folding a sequence of distinct operations into a single statement.

If you do find yourself (or your staff) programming in C, the attitude with which you approach the task has a lot to do with whether you conquer C or it conquers you. To successfully program in C, you can't just memorize more C rules, code more carefully, and keep the debugger close at hand. You have to start with an awareness of what types of languages C and C++ are, and plan your strategy for preventing accidents. With some forewarning, and the right attitude, it's not terribly difficult to do, although compared to other languages, C can remain a frustratingly primitive — and C++ an agitatingly complex — way to write software.

There are some bright spots in the world of C programming, however. If you don't succumb to the "this is the way all C programmers do it" method of programming, you can enjoy the benefits of an enormous collection of C and C++ source and executable libraries, and a large set of C-related tools, such as "C-aware" editors and programmer workbenches. And there's no question that the fierce competition among C compiler vendors, especially on the PC, has produced excellent and affordable C compilers. The performance of well-designed C programs compiled with one of the good optimizing compilers is usually excellent, too.

So don't fear that the only result of programming in C is spending large amounts of time chasing wild pointers. With the right amount of respect for the language and not too much respect for C "traditions," you can enjoy the advantages of the broad C compiler and tools market. All it takes is going into it with your eyes wide open and programming with a little "common sense."


Previous Table of Contents Next