Programming/Software Engineering
The Practice of Programming
With the same insight and authority that made their book The Unix Programming
Environment a classic, Brian Kernighan and Rob Pike have written The Practice
o f Programming to help make individual programmers more effective and
productive.
The practice of programming is more than just writing code. Programmers must
also assess tradeoffs, choose among design alternatives, debug and test, improve
performance, and maintain software written by themselves and others. At the
same time, they must be concerned with issues like compatibility, robustness,
and reliability, while meeting specifications.
The Practice o f Programming covers all these topics, and more. This book is full
of practical advice and real-world examples in C, C++, lava, and a variety of
special-purpose languages. It includes chapters on:
debugging: finding bugs quickly and methodically
testing: guaranteeing that software works correctly and reliably
performance: making programs faster and more compact
portability: ensuring that programs run everywhere without change
design: balancing goals and constraints to decide which algorithms and data
structures are best
interfaces: using abstraction and information hiding to control the interactions
between components
style: writing code that works well and is a pleasure to read
notation: choosing languages and tools that let the machine do more of the
work
Kernighan and Pike have distilled years of experience writing programs,
teaching, and working with other programmers to create this book. Anyone who
writes software will profit from the principles and guidance in The Practice o f
Programming.
Brian W. Kernighan and Rob Pike work in the Computing Science Research
Center at Bell Laboratories, Lucent Technologies. Brian Kernighan is Consulting
Editor for Addison-Wesley's Professional Computing Series and the author, with
Dennis Ritchie, of The C Programming Language. Rob Pike was a lead architect
and implementer of the Plan 9 and Inferno operating systems. His research
focuses on software that makes it easier for people to write software
Cover art by Renee French
QText printed on recycled paper
h ADDISON-WESLEY
Addison-Wesley is an imprint of
Addison Wesley Longman, Inc.
The Practice of Programming
Many of the designations used by manufacturers and sellers to distinguish their products are
claimed as trademarks. Where those designations appear in this book, and Addison Wesley
Longman, Inc. was aware of a trademark claim. the designations have been printed in initial
capital letters or all capital letters.
The authors and publisher have taken care in preparation of this book, but make no expressed or
implied warranty of any kind and assume no responsibility for errors or omissions. No liability is
assumed for incidental or consequential damages in connection with or arising out of the use of
the information or programs contained herein,
The publisher offers discounts of this book when ordered in quantity for special sales. For more
information, please contact:
Computer and Engineering Publishing Group
Addison Wesley Longman, Inc.
One Jacob Way
Reading, Massachusetts 01 867
This book was typeset (gri~l~l)icltI)Ilqnlt~nff
authors.
-nip) in Times and Lucida Sans Typewriter by the
Library of Congress Cataloging-in-Publication Data
Kernighan, Brian W.
The practice of programming 1 Brian W. Kernighan, Rob Pike.
p. cm. -- (Addison-Wesley professional computing series)
Includes bibliographical references.
ISBN 0-201 -6 1586-X
1. Computer programming. I. Pike, Rob. 11. Title. 111. Series.
QA76.6 .K48 1999
005.1--dc2 1
99-10131
CIP
Copyright O 1999 by Lucent Technologies.
All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or
transmitted. in any form or by any means, electronic, mechanical, photocopying, recording, or
otherwise, without the prior written permission of the publisher. Printed in the United States of
America. Published simultaneously in Canada.
Text printed on recycled and acid-free paper.
ISBN 0-201-61586-X
2 3 4 5 6 7 CRS 02010099
2nd Printing May 1999
Contents
Preface
Chapter 1: Style
1.1 Names
1.2 Expressions and Statements
1.3 Consistency and Idioms
1.4 Function Macros
1.5 Magic Numbers
1.6 Comments
1.7 Why Bother?
Chapter 2: Algorithms and Data Structures
2.1 Searching
2.2 Sorting
2.3 Libraries
2.4 A Java Quicksort
2.5 0-Notation
2.6 Growing Arrays
2.7 Lists
2.8 Trees
2.9 Hash Tables
2.10 Summary
Chapter 3: Design and Implementation
3.1 The Markov Chain Algorithm
3.2 Data Structure Alternatives
3.3 Building the Data Suucture in C
3.4 Generating Output
3.5 Java
3.6 C++
3.7 AwkandPerl
3.8 Performance
3.9 Lessons
Chapter 4: Interfaces
4.1 Comma-Separated Values
4.2 A Prototype Library
4.3 A Library for Others
4.4 A C++ Implementation
4.5 Interface Principles
4.6 Resource Management
4.7 Abort, Retry. Fail?
4.8 User Interfaces
Chapter 5: Debugging
5.1 Debuggers
5.2 Good Clues, Easy Bugs
5.3 No Clues, Hard Bugs
5.4 Last Resorts
5.5 Non-reproducible Bugs
5.6 Debugging Tools
5.7 Other People's Bugs
5.8 Summary
Chapter 6: Testing
6.1 Test as You Write the Code
6.2 Systematic Testing
6.3 Test Automation
6.4 Test Scaffolds
6.5 Stress Tests
6.6 Tips for Testing
6.7 Who Does the Testing?
6.8 Testing the Markov Program
6.9 Summary
Chapter 7: Performance
7.1 A Bottleneck
7.2 Timing and Profiling
7.3 Strategies for Speed
7.4 Tuning the Code
7.5 Space Efficiency
7.6 Estimation
7.7 Summary
Chapter 8: Portability
8.1 Language
8.2 Headers and Libraries
8.3 Program Organization
8.4 Isolation
8.5 Data Exchange
8.6 Byte Order
8.7 Portability and Upgrade
8.8 Internationalization
8.9 Summary
Chapter 9: Notation
9.1 Formatting Data
9.2 Regular Expressions
9.3 Programmable Tools
9.4 Interpreters, Compilers, and Virtual Machines
9.5 Programs that Write Programs
9.6 Using Macros to Generate Code
9.7 Compiling on the Fly
Epilogue
Appendix: Collected Rules
Index
Preface
Have you ever ...
wasted a lot of time coding the wrong algorithm?
used a data structure that was much too complicated?
tested a program but missed an obvious problem?
spent a day looking for a bug you should have found in five minutes?
needed to make a program run three times faster and use less memory?
struggled to move a program from a workstation to a PC or vice versa?
tried to make a modest change in someone else's program?
rewritten a program because you couldn't understand it?
Was it fun?
These things happen to programmers all the time. But dealing with such problems
is often harder than it should be because topics like testing, debugging, portability,
performance, design alternatives, and style-the practice of programming-are not
usually the focus of computer science or programming courses. Most programmers
learn them haphazardly as their experience grows, and a few never learn them at all.
In a world of enormous and intricate interfaces, constantly changing tools and lan-
guages and systems, and relentless pressure for more of everything, one can lose sight
of the basic principles-simplicity, clarity, generality-that form the bedrock of good
software. One can also overlook the value of tools and notations that mechanize some
of software creation and thus enlist the computer in its own programming.
Our approach in this book is based on these underlying, interrelated principles,
which apply at all levels of computing. These include simpliciry, which keeps pro-
grams short and manageable; clariry, which makes sure they are easy to understand,
for people as well as machines; generality, which means they work well in a broad
range of situations and adapt well as new situations arise; and automation, which lets
the machine do the work for us, freeing us from mundane tasks. By looking at com-
puter programming in a variety of languages, from algorithms and data structures
through design, debugging, testing, and performance improvement, we can illustrate