Previous | Table of Contents | Next |
Order in the Court
In Chapters 2 and 6, I pointed out some of the problems that arise from Cs rules (or lack of rules) for operator precedence and order of evaluation of expressions. I wont go through all the rules or unusual results that can occur, but observe that an expression like
r = x * y * z;
may be evaluated as
tmp = x * y; r = tmp * z;
or as
tmp = y * z; r = x * tmp;
Note that even parentheses will not guarantee the ordering, and even (x * y) * z may be evaluated as
tmp = y * z; r = x * tmp;
In many cases, it may not matter what the order of evaluation is, but if it does, you should use separate statements to specify order-dependent operations.
The Name Game
As if C didnt offer enough problems on its own, the C programming culture sometimes seems to strive to create more traps for the unwary. One example is the widely used Hungarian naming convention, which uses partial capitalization for identifiers. Because C is case-sensitive, a variable hDlg is different than the variable hdlg. Woe to the programmer who has identifiers that differ only in case. Not only is there the obvious potential for elusive errors caused by typing mistakes, but some link editors change all global symbols to uppercase when linking multiple files, causing both hDlg and hdlg to be treated as HDLG.
You wont be able to avoid Hungarian notation when you work with some vendor-supplied libraries, such as the Microsoft Windows interface. But for your own code, especially global variables: Avoid identifiers that differ only in the case (i.e., upper and lower) of some letters. I recommend the simple, less error-prone, standard of using all lowercase identifiers, except for manifest constants. You should also be careful with some older link editors that may truncate global identifiers (the C standard requires only that the first 6 characters of an external identifier be used), causing the potential for additional collisions.
Although Ive covered lots of C danger zones in the last 6 chapters, there are more waiting. Among the areas to watch carefully are: casting pointers; using C signals (Koenig has an enlightening and alarming discussion on using signals); using floating-point variables to approximate decimal values (such as currency); and portability problems, such as character representations and byte ordering. The books listed in Appendix A provide additional material on these topics. The principle that underlies all these rules is: Tread carefully in C; stick to simple and well-understood techiniques; and avoid clever programming. The truly clever C programmer is also an extremely cautious one.
C Coding Suggestions
Previous | Table of Contents | Next |