Preface
Acknowledgments
Chapter 1 Basics
Gotcha#1:ExcessiveCommenting
Gotcha#2:Magic Numbers
Gotcha#3:Global Variables
Gotcha#4:Failure to Distinguish Overloading from Default Initialization
Gotcha#5:Misunderstanding References
Gotcha#6:Misunderstanding Const
Gotcha#7:Ignorane of Base Language Subtleties
Gotcha#8:Failure to Distinguish Access and Visibility
Gotcha#9:Using Bad Language
Gotcha#10:Ignoranceof Idiom
Gotcha#11:Unnecessary Cleverness
Gotcha#12:Adolescent Behavior
Chapter2 Syntax
Gotcha#13:Array/Initializer Confusion
Gotcha#14:Evaluation Order Indecision
Gotcha#15:Precedence Problems
Gotcha#16:for Statement Debacle
Gotcha#17:Maximal Munch Problems
Gotcha#18:Creative Declaration-Specifier Ordering
Gotcha#19:Function/ObjectAmbiguity
Gotcha#20:Migrating Type-Qualifiers
Gotcha#21:Self-Initialization
Gotcha#22:Staticand Extern Types
Gotcha#23:Operator Function Lookup Anomaly
Gotcha#24:Operator->Subtleties
Chapter3 The Preprocessor
Gotcha#25:#define Literals
Gotcha#26:#define Pseudofunctions
Gotcha#27:Overuse of #if
Gotcha#28:Side Effects in Assertions
Chapter4 Conversions
Gotcha#29:Converting through void
Gotcha#30:Slicing
Gotcha#31:Misunderstanding Pointer-to-Const Conversion
Gotcha#32:Misunderstanding Pointer-to-Pointer-to-Const Conversion
Gotcha#33:Misunderstanding Pointer-to -Base Conversion
Gotcha#34:Pointer-to-Multidimensional-Array Problems
Gotcha#35:Unchecked Downcasting
Gotcha#36:Casting under Multiple Inheritance
Gotcha#37:Unintended Constructor Conversion
Gotcha#38:Casting under Multiple Inheritance
Gotcha#39:Casting Incomplete Types
Gotcha#40:Old-Stykle Casts
Gotcha#41:Static Casts
Gotcha#42:Temporary Initialization of Formal Arguments
Gotcha#43:Temporary Lifetime
Gotcha#44:References and Temporaries
Gotcha#45:AmbiguityuFailure of dynamic_cast
Chapter5 Initialization
Gotcha#46:Misunderstanding Contravariance
Gotcha#47:Assignment/Initialization Confusion
Gotcha#48:Improperly Scoped Variables
Gotcha#49:Failure to Appreciate C ''s Fixation on Copy Operations
Gotcha#50:Bitwise Copy of Class Objects
Gotcha#51:Confusing Initialization and Assignment in Constructors
Gotcha#52:Inconsistent Ordering of the Member Initialization List
Gotcha#53:Virtual Base Default Initialization
Gotcha#54:Copy Constructor Base Initialization
Gotcha#55:Runtime Static Initialization Order
Gotcha#56:Durect versys Copy Initialization
Gotcha#57:Direct Argument Initialization
Gotcha#58:Ignorance of the Return Value Optimizations
Gotcha#59:Initializing a Static Member in a Constructor
Chapter6 Memory and Resource Management
Gotcha#60:Failure to Distinguish Scalar and Array Allocation
Gotcha#61:Checking for Allocation Failure
Gotcha#62:Replacing Global New and Delete
Gotcha#63:Confusing Scope and Activation of Member new and delete
Gotcha#64:Throwing String Literals
Gotcha#65:Improper Exception Mechanics
Gotcha#66:Abusing Local Addresses
Gotcha#67:Failure to Employ Resource Acquisition Is Initialization
Gotcha#68:Improper Use of auto_ptr
Chapter7 Polymorphism
Gotcha#69:Type Codes
Gotcha#70:Nonvirtual Base Class Destructor
Gotcha#71:Hiding Nonvirtual Functions
Gotcha#72:Making Template Methods Too Flexible
Gotcha#73:Overloading Virtual Functions
Gotcha#74:VirtualFunctions with Default Argument Initializers
Gotcha#75:Calling Virtual Functions in Constructors and Destructors
Gotcha#76:Virtual Assignment
Gotcha#77:Failure toDistinguish among Overloading,Overriding,and Hiding
Gotcha#78:Failure to Grok Virtual Functions and Overriding
Gotcha#79:Dominance Issues
Chapter8 Class Design
Gotcha#80:Get/Set Interfaces
Gotcha#81:Const and Reference Data Members
Gotcha#82:Not Understanding theMeaning of Const Member Functions
Gotcha#83:Failure to Distinguish Aggregation and Acquaintance
Gotcha#84:Improper Operator Overloading
Gotcha#85:Precedence and Overloading
Gotcha#86:Friend versus Member Operators
Gotcha#87:Problems with Increment and Decrement
Gotcha#88:Misunderstanding Templated Copy Operations
Chapter9 Hierarchy Design
Gotcha#89:Arrays of Class Objects
Gotcha#90:Improper Container Substitutability
Gotcha#91:Failure toUnderstand Protected Access
Gotcha#92:Public Inheritance for Code Reuse
Gotcha#93:Concrete Public Base Classes
Gotcha#94:Failure to Employ Degenerate Hierarchies
Gotcha#95:Overuse of Inheritance
Gotcha#96:Type-Based Control Structures
Gotcha#97:Cosmic Hierarchies
Gotcha#98:Asking Personal Questions of an Object
Gotcha#99:Capability Queries
Bibliography
Indeximportant, mentioning the application of a particular pattern serves to document not only the technique applied but also the reasons for its application and the effect of having applied it.
For example, when we see that the Bridge pattern has been applied to a design, we know at a mechanical level that an abstract data type implementation has been separated into an interface class and an implementation class. Additionally, we know this was done to separate strongly the interface from the implementation, so changes to the implementation won''t affect users of the interface. We also know this separation entails a runtime cost, how the source code for the abstract data type should be arranged, and many other details.
A pattern name is an efficient, unambiguous handle to a wealth of information and experience about a technique. Careful, accurate use of patterns and pattern terminology in design and documentation clarifies code and helps prevent gotchas from occurring.
C
is a complex programming language, and the more complex a language, the more important is the use of idiom in programming. For a programming language, an idiom is a commonly used and generally understood combination of lower-level language features that produces a higher-level construct, in much the same way patterns do at higher levels of design. Therefore, in C
we can discuss copy operations, function objects, smart pointers, and throwing an exception without having to specify these concepts at their lowest level of implementation.
It''s important to emphasize that an idiom is not only a common combination of language features but also a common set of expectations about how these combined features should behave. What do copy operations mean What can we expect to happen when an exception is thrown Much of the advice found in this book involves being aware of and employing idioms in C
coding and design.
Many of the gotchas listed here could be described simply as departing from a particular C
idiom, and the accompanying solution to the problem could often be described simply as following the appropriate idiom see Gotcha #10 .
A significant portion of this book is spent describing the nuances of certain areas of the C
language that are commonly misunderstood and frequently lead to gotchas. While some of this material may have an esoteric feel to it, unfamiliarity with these areas is a source of problems and a barrier to expert use of C . These dark corners also make an interesting and profitable study in themselves. They are in C
for a reason, and expert C
programmers often find use for them in advanced programming and design.
Another area of connection between gotchas and design patterns is the similar importance of describing relatively simple instances. Simple patterns are important. In some respects, they may be more important than technically difficult patterns, because they''re likely to be more commonly employed. The benefits obtained from the pattern description will, therefore, be leveraged over a larger body of code and design.
In much the same way, the gotchas described in this book cover a wide range of difficulty, from a simple exhortation to act like a responsible professional Gotcha #12 to warnings to avoid misunderstanding the dominance rule under virtual inheritance Gotcha #79 . But, as in the analogous case with patterns, acting responsibly is probably more commonly applicable on a day-to-day basis than is the dominance rule.
Two common themes run through the presentation. The first is the overriding importance of convention. This is especially important in a complex language like C . Adherence to established convention allows us to communicate efficiently and accurately with others. The second theme is the recognition that others will maintain the code we write. The maintenance may be direct, so that our code must be readily and generally understood by competent maintainers, or it may be indirect, in which case we must ensure that our code remains correct even as its behavior is modified by remote changes.
The gotchas in this book are presented as a collection of short essays, each of which describes a gotcha or set of related gotchas, along with suggestions for avoiding or correcting them. I''m not sure any book about gotchas can be entirely cohesive, due to the anarchistic nature of the subject. However, the gotchas are grouped into chapters according to their general nature or area of mis applicability. Additionally, discussion of one gotcha inevitably touches on others. Where it makes sense to do so---and it generally does--I''ve made these links explicit.
Cohesion within each item is sometimes at risk as well. Often it''s necessary, before getting to the description of a gotcha, to describe the context in which it appears. That description, in turn, may require discussion of a technique, idiom, pattern, or language nuance that may lead us even further afield before we return to the advertised gotcha. I''ve tried to keep this meandering to a minimum, but it would have been dishonest, I think, to attempt to avoid it entirely. Effective programming in C
involves intelligent coordination of so many disparate areas
that it''s impractical to imagine one can examine its etiology effectively without involving a similar eclectic collection of topics.
It''s certainly not necessary--and possibly inadvisable--to read this book straight through, from Gotcha #1 to Gotcha #99. Such a concentrated dose of mayhem may put you off programming in C
altogether. A better approach may be to start with a gotcha you''ve experienced or that sounds interesting and follow links to related gotchas. Alternatively, you may sample the gotchas at random.
The text employs a number of devices intended to darify the presentation. First,incorrect or inadvisable code is indicated by a gray background, whereas correct and proper code is presented with no background. Second, code that appears in the text has been edited for brevity and clarity. As a result, the examples as presented often won''t compile without additional, supporting code. The source code for nontrivial examples is available from the author''s Web site: www. semantics.org. All such code is indicated in the text by an abbreviated pathname near the code example, as in gotchaOO/somecode.cpp.
Finally, a warning: the one thing you should not do with gotchas is elevate them to the same status as idioms or patterns. One of the signs that you''re using patterns and idioms properly is that the pattern or idiom appropriate to the design or coding context will arise spontaneous] , from your subconscious just when you need it.
Recognition of a gotcha is analogous to a conditioned response to danger: once burned, twice shy. However, as with matches and firearms, it''s not necessary to suffer a burn or a gunshot wound to the head personally to learn how to recognize and avoid a dangerous situation; generally, all that''s necessary is advance warning.
Consider this collection a means to keep your head in the face of C
gotchas.
Stephen C. Dewhurst
Carver, Massachusetts
July 2002