Write Great Code, Volume 2, 2nd Edition - Thinking Low-Level, Writing High-Level (Randall Hyde) (Z-Library)

Author: Randall Hyde

科学

Thinking Low-Level, Writing High-Level, the second volume in the landmark Write Great Code series by Randall Hyde, covers high-level programming languages (such as Swift and Java) as well as code generation on 64-bit CPUsARM, the Java Virtual Machine, and the Microsoft Common Runtime. Today's programming languages offer productivity and portability, but also make it easy to write sloppy code that isn't optimized for a compiler. Thinking Low-Level, Writing High-Level will teach you to craft source code that results in good machine code once it's run through a compiler. You'll learn: • How to analyze the output of a compiler to verify that your code generates good machine code • The types of machine code statements that compilers generate for common control structures, so you can choose the best statements when writing HLL code • Enough assembly language to read compiler output • How compilers convert various constant and variable objects into machine data With an understanding of how compilers work, you'll be able to write source code that they can translate into elegant machine code. NEW TO THIS EDITION, COVERAGE OF: • Programming languages like Swift and Java • Code generation on modern 64-bit CPUs • ARM processors on mobile phones and tablets • Stack-based architectures like the Java Virtual Machine • Modern langua

📄 File Format: PDF
💾 File Size: 4.7 MB
14
Views
0
Downloads
0.00
Total Donations

📄 Text Preview (First 20 pages)

ℹ️

Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

📄 Page 1
R A N D A L L H Y D E W R I T E G R E A T C O D E / V O L U M E 2 T H I N K I N G L O W L E V E L , W R I T I N G H I G H L E V E L 2 N D E D I T I O N
📄 Page 2
(This page has no text content)
📄 Page 3
PRAISE FOR THE FIRST EDITION OF WRITE GREAT CODE, VOLUME 2 “Set aside some money and buy this book, or get a friend to buy it and get it from them while still in the store. When you get home, read it TWICE so that you master what is in these pages. Then read it again.” —DevCity “Write Great Code, Volume 2, exceeds its goal of helping developers pay more attention to application performance when writing applications in high-level languages. This book is a must for any high-level application developer.” —Free SoFtware Magazine “As a high-level-language programmer, if you want to know what’s really going on with your programs, you need to spend a little time learning assembly language—and you won’t find an easier introduction.” —DevX “This is a good book. A very, very good book. Frankly, I’m blown away at the quality of writing.” —toronto ruby uSer group
📄 Page 4
(This page has no text content)
📄 Page 5
by Randall Hyde San Francisco W R I T E G R E AT C O D E V O L U M E 2 2 N D E D I T I O N T h i n k i n g L o w - L e v e l, W r i t i n g H i g h - L e v e l
📄 Page 6
WRITE GREAT CODE, Volume 2: Thinking Low-Level, Writing High-Level, 2nd Edition. Copyright © 2020 by Randall Hyde. All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system, without the prior written permission of the copyright owner and the publisher. ISBN-10: 1-59327-855-1 ISBN-13: 978-1-59327-855-7 Publisher: William Pollock Executive Editor: Barbara Yien Production Editor: Rachel Monaghan Developmental Editor: Athabasca Witschi Project Editor: Dapinder Dosanjh Cover and Interior Design: Octopod Studios Technical Reviewer: Anthony Tribelli Copyeditor: Rachel Monaghan Compositor: Danielle Foster Proofreader: James Fraleigh Illustrator: David Van Ness For information on distribution, translations, or bulk sales, please contact No Starch Press, Inc. directly: No Starch Press, Inc. 245 8th Street, San Francisco, CA 94103 phone: 1.415.863.9900; info@nostarch.com www.nostarch.com The Library of Congress issued the following Cataloging-in-Publication Data for the first edition of Volume 1: Hyde, Randall. Write great code : understanding the machine / Randall Hyde. p. cm. ISBN 1-59327-003-8 1. Computer programming. 2. Computer architecture. I. Title. QA76.6.H94 2004 005.1--dc22 2003017502 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names mentioned herein may be the trademarks of their respective owners. Rather than use a trademark symbol with every occurrence of a trademarked name, we are using the names only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark. The information in this book is distributed on an “As Is” basis, without warranty. While every precaution has been taken in the preparation of this work, neither the author nor No Starch Press, Inc. shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in it.
📄 Page 7
About the Author Randall Hyde is the author of The Art of Assembly Language and Write Great Code, Volumes 1, 2, and 3 (all from No Starch Press), as well as Using 6502 Assembly Language and P-Source (Datamost). He is also the coauthor of Microsoft Macro Assembler 6.0 Bible (The Waite Group). Over the past 40 years, Hyde has worked as an embedded software/hardware engineer developing instrumentation for nuclear reactors, traffic control systems, and other consumer elec- tronics devices. He has also taught computer science at California State Polytechnic University, Pomona, and at the University of California, Riverside. His website is www.randallhyde.com/. About the Technical Reviewer Tony Tribelli has more than 35 years of experience in software development, including work on embedded device kernels and molecular modeling. He developed video games for 10 years at Blizzard Entertainment. He is currently a software develop- ment consultant and privately develops applications utilizing computer vision.
📄 Page 8
(This page has no text content)
📄 Page 9
B R I E F C O N T E N T S Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix Chapter 1: Thinking Low-Level, Writing High-Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Chapter 2: Shouldn’t You Learn Assembly Language? . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Chapter 3: 80x86 Assembly for the HLL Programmer . . . . . . . . . . . . . . . . . . . . . . . . . 17 Chapter 4: Compiler Operation and Code Generation . . . . . . . . . . . . . . . . . . . . . . . . 47 Chapter 5: Tools for Analyzing Compiler Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Chapter 6: Constants and High-Level Languages . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 Chapter 7: Variables in a High-Level Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 Chapter 8: Array Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Chapter 9: Pointer Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 Chapter 10: String Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 Chapter 11: Record, Union, and Class Data Types . . . . . . . . . . . . . . . . . . . . . . . . . 331 Chapter 12: Arithmetic and Logical Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 Chapter 13: Control Structures and Programmatic Decisions . . . . . . . . . . . . . . . . . . . 451 Chapter 14: Iterative Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 503 Chapter 15: Functions and Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535 Afterword: Engineering Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 599 Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601 Online Appendixes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 607 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609
📄 Page 10
(This page has no text content)
📄 Page 11
C O N T E N T S I N D E T A I L ACKNOWLEDGMENTS xvii INTRODUCTION xix Performance Characteristics of Great Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xx The Goal of This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxii Chapter Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxii Assumptions and Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xxiii The Environment for This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xxiii For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xxiv 1 THINKING LOW-LEVEL, WRITING HIGH-LEVEL 1 1 .1 Misconceptions About Compiler Quality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1 .2 Why Learning Assembly Language Is Still a Good Idea . . . . . . . . . . . . . . . . . . . . 2 1 .3 Why Learning Assembly Language Isn’t Absolutely Necessary . . . . . . . . . . . . . . . . 3 1 .4 Thinking Low-Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1 .4 .1 Compilers Are Only as Good as the Source Code You Feed Them . . . . . 4 1 .4 .2 How to Help the Compiler Produce Better Machine Code . . . . . . . . . . . 4 1 .4 .3 How to Think in Assembly While Writing HLL Code . . . . . . . . . . . . . . . 5 1 .5 Writing High-Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1 .6 Language-Neutral Approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1 .7 Additional Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1 .8 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2 SHOULDN’T YOU LEARN ASSEMBLY LANGUAGE? 9 2 .1 Benefits and Roadblocks to Learning Assembly Language . . . . . . . . . . . . . . . . . . 10 2 .2 How This Book Can Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 2 .3 High-Level Assemblers to the Rescue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2 .4 High-Level Assembly Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2 .5 Thinking High-Level, Writing Low-Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2 .6 The Assembly Programming Paradigm (Thinking Low-Level) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2 .7 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3 80X86 ASSEMBLY FOR THE HLL PROGRAMMER 17 3 .1 Learning One Assembly Language Is Good, Learning More Is Better . . . . . . . . . . 18 3 .2 80x86 Assembly Syntaxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 3 .2 .1 Basic 80x86 Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3 .2 .2 Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
📄 Page 12
x 3 .2 .3 80x86 32-Bit General-Purpose Registers . . . . . . . . . . . . . . . . . . . . . . 20 3 .2 .4 The 80x86 EFLAGS Register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3 .3 Literal Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 3 .3 .1 Binary Literal Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3 .3 .2 Decimal Literal Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3 .3 .3 Hexadecimal Literal Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 3 .3 .4 Character and String Literal Constants . . . . . . . . . . . . . . . . . . . . . . . 25 3 .3 .5 Floating-Point Literal Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3 .4 Manifest (Symbolic) Constants in Assembly Language . . . . . . . . . . . . . . . . . . . . 27 3 .4 .1 Manifest Constants in HLA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3 .4 .2 Manifest Constants in Gas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3 .4 .3 Manifest Constants in MASM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3 .5 80x86 Addressing Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3 .5 .1 80x86 Register Addressing Modes . . . . . . . . . . . . . . . . . . . . . . . . . 28 3 .5 .2 Immediate Addressing Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 3 .5 .3 Displacement-Only Memory Addressing Mode . . . . . . . . . . . . . . . . . 30 3 .5 .4 RIP-Relative Addressing Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3 .5 .5 Register Indirect Addressing Mode . . . . . . . . . . . . . . . . . . . . . . . . . . 32 3 .5 .6 Indexed Addressing Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3 .5 .7 Scaled-Index Addressing Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3 .6 Declaring Data in Assembly Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3 .6 .1 Data Declarations in HLA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3 .6 .2 Data Declarations in MASM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3 .6 .3 Data Declarations in Gas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3 .7 Specifying Operand Sizes in Assembly Language . . . . . . . . . . . . . . . . . . . . . . . 43 3 .7 .1 Type Coercion in HLA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3 .7 .2 Type Coercion in MASM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3 .7 .3 Type Coercion in Gas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3 .8 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 4 COMPILER OPERATION AND CODE GENERATION 47 4 .1 File Types That Programming Languages Use . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4 .2 Source Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4 .2 .1 Tokenized Source Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4 .2 .2 Specialized Source Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 4 .3 Types of Computer Language Processors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 4 .3 .1 Pure Interpreters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 4 .3 .2 Interpreters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 4 .3 .3 Compilers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 4 .3 .4 Incremental Compilers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 4 .4 The Translation Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 4 .4 .1 Scanning (Lexical Analysis) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 4 .4 .2 Parsing (Syntax Analysis) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 4 .4 .3 Intermediate Code Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 4 .4 .4 Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 4 .4 .5 Compiler Benchmarking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4 .4 .6 Native Code Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4 .5 Compiler Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4 .5 .1 Emitting HLL Code as Compiler Output . . . . . . . . . . . . . . . . . . . . . . . 67 4 .5 .2 Emitting Assembly Language as Compiler Output . . . . . . . . . . . . . . . . 69
📄 Page 13
xi 4 .5 .3 Emitting Object Files as Compiler Output . . . . . . . . . . . . . . . . . . . . . 70 4 .5 .4 Emitting Executable Files as Compiler Output . . . . . . . . . . . . . . . . . . 71 4 .6 Object File Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 4 .6 .1 The COFF File Header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 4 .6 .2 The COFF Optional Header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 4 .6 .3 COFF Section Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 4 .6 .4 COFF Sections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 4 .6 .5 The Relocation Section . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 4 .6 .6 Debugging and Symbolic Information . . . . . . . . . . . . . . . . . . . . . . . . 80 4 .7 Executable File Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 4 .7 .1 Pages, Segments, and File Size . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 4 .7 .2 Internal Fragmentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 4 .7 .3 Reasons to Optimize for Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 4 .8 Data and Code Alignment in an Object File . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 4 .8 .1 Choosing a Section Alignment Size . . . . . . . . . . . . . . . . . . . . . . . . . 86 4 .8 .2 Combining Sections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 4 .8 .3 Controlling the Section Alignment . . . . . . . . . . . . . . . . . . . . . . . . . . 87 4 .8 .4 Aligning Sections Within Library Modules . . . . . . . . . . . . . . . . . . . . . 88 4 .9 How Linkers Affect Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 4 .10 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 5 TOOLS FOR ANALYZING COMPILER OUTPUT 99 5 .1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 5 .2 Telling a Compiler to Produce Assembly Output . . . . . . . . . . . . . . . . . . . . . . . . 101 5 .2 .1 Assembly Output from GNU Compilers . . . . . . . . . . . . . . . . . . . . . 102 5 .2 .2 Assembly Output from Visual C++ . . . . . . . . . . . . . . . . . . . . . . . . . 102 5 .2 .3 Example Assembly Language Output . . . . . . . . . . . . . . . . . . . . . . . 102 5 .2 .4 Assembly Output Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 5 .3 Using Object Code Utilities to Analyze Compiler Output . . . . . . . . . . . . . . . . . 112 5 .3 .1 The Microsoft dumpbin .exe Utility . . . . . . . . . . . . . . . . . . . . . . . . . 112 5 .3 .2 The FSF/GNU objdump Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 5 .4 Using a Disassembler to Analyze Compiler Output . . . . . . . . . . . . . . . . . . . . . 127 5 .5 Using the Java Bytecode Disassembler to Analyze Java Output . . . . . . . . . . . . . 130 5 .6 Using the IL Disassembler to Analyze Microsoft C# and Visual Basic Output . . . . 132 5 .7 Using a Debugger to Analyze Compiler Output . . . . . . . . . . . . . . . . . . . . . . . . 134 5 .7 .1 Using an IDE’s Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 5 .7 .2 Using a Stand-Alone Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 5 .8 Comparing Output from Two Compilations . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 5 .8 .1 Before-and-After Comparisons with diff . . . . . . . . . . . . . . . . . . . . . . 138 5 .9 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 6 CONSTANTS AND HIGH-LEVEL LANGUAGES 145 6 .1 Literal Constants and Program Efficiency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 6 .2 Binding Times . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 6 .3 Literal Constants vs . Manifest Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 6 .4 Constant Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 6 .5 Manifest Constants vs . Read-Only Memory Objects . . . . . . . . . . . . . . . . . . . . . 153 6 .6 Swift let Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
📄 Page 14
xii 6 .7 Enumerated Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 6 .8 Boolean Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 6 .9 Floating-Point Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 6 .10 String Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 6 .11 Composite Data Type Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 6 .12 Constants Don’t Change . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 6 .13 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 7 VARIABLES IN A HIGH-LEVEL LANGUAGE 173 7 .1 Runtime Memory Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 7 .1 .1 The Code, Constant, and Read-Only Sections . . . . . . . . . . . . . . . . . 175 7 .1 .2 The Static Variables Section . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 7 .1 .3 The Storage Variables Section . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 7 .1 .4 The Stack Section . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 7 .1 .5 The Heap Section and Dynamic Memory Allocation . . . . . . . . . . . . . 179 7 .2 What Is a Variable? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 7 .2 .1 Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 7 .2 .2 Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 7 .2 .3 Static Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 7 .2 .4 Dynamic Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 7 .2 .5 Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 7 .2 .6 Lifetime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 7 .2 .7 Variable Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 7 .3 Variable Storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 7 .3 .1 Static Binding and Static Variables . . . . . . . . . . . . . . . . . . . . . . . . . 183 7 .3 .2 Pseudo-Static Binding and Automatic Variables . . . . . . . . . . . . . . . . 187 7 .3 .3 Dynamic Binding and Dynamic Variables . . . . . . . . . . . . . . . . . . . . 189 7 .4 Common Primitive Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 7 .4 .1 Integer Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 7 .4 .2 Floating-Point/Real Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 7 .4 .3 Character Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 7 .4 .4 Boolean Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 7 .5 Variable Addresses and High-Level Languages . . . . . . . . . . . . . . . . . . . . . . . . 198 7 .5 .1 Allocating Storage for Global and Static Variables . . . . . . . . . . . . . 199 7 .5 .2 Using Automatic Variables to Reduce Offset Sizes . . . . . . . . . . . . . . 200 7 .5 .3 Allocating Storage for Intermediate Variables . . . . . . . . . . . . . . . . . 206 7 .5 .4 Allocating Storage for Dynamic Variables and Pointers . . . . . . . . . . 207 7 .5 .5 Using Records/Structures to Reduce Instruction Offset Sizes . . . . . . . . 209 7 .5 .6 Storing Variables in Machine Registers . . . . . . . . . . . . . . . . . . . . . . 210 7 .6 Variable Alignment in Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 7 .6 .1 Records and Alignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 7 .7 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 8 ARRAY DATA TYPES 225 8 .1 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 8 .1 .1 Array Declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 8 .1 .2 Array Representation in Memory . . . . . . . . . . . . . . . . . . . . . . . . . . 231 8 .1 .3 Swift Array Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
📄 Page 15
xiii 8 .1 .4 Accessing Elements of an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 8 .1 .5 Padding vs . Packing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 8 .1 .6 Multidimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 8 .1 .7 Dynamic vs . Static Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 8 .2 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 9 POINTER DATA TYPES 267 9 .1 The Definition of a Pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 9 .2 Pointer Implementation in High-Level Languages . . . . . . . . . . . . . . . . . . . . . . . . 269 9 .3 Pointers and Dynamic Memory Allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 9 .4 Pointer Operations and Pointer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 9 .4 .1 Adding an Integer to a Pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 9 .4 .2 Subtracting an Integer from a Pointer . . . . . . . . . . . . . . . . . . . . . . . 275 9 .4 .3 Subtracting a Pointer from a Pointer . . . . . . . . . . . . . . . . . . . . . . . . 275 9 .4 .4 Comparing Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 9 .4 .5 Using Logical AND/OR Operations with Pointers . . . . . . . . . . . . . . 278 9 .4 .6 Using Other Operations with Pointers . . . . . . . . . . . . . . . . . . . . . . . 279 9 .5 A Simple Memory Allocator Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 9 .6 Garbage Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 9 .7 The OS and Memory Allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 9 .8 Heap Memory Overhead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 9 .9 Common Pointer Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 9 .9 .1 Using an Uninitialized Pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 9 .9 .2 Using a Pointer That Contains an Illegal Value . . . . . . . . . . . . . . . . . 287 9 .9 .3 Continuing to Use Storage After It Has Been Freed . . . . . . . . . . . . . . 287 9 .9 .4 Failing to Free Storage After Using It . . . . . . . . . . . . . . . . . . . . . . . 288 9 .9 .5 Accessing Indirect Data Using the Wrong Data Type . . . . . . . . . . . . 289 9 .9 .6 Performing Illegal Operations on Pointers . . . . . . . . . . . . . . . . . . . . 290 9 .10 Pointers in Modern Languages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 9 .11 Managed Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 9 .12 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 10 STRING DATA TYPES 293 10 .1 Character String Formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294 10 .1 .1 Zero-Terminated Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 10 .1 .2 Length-Prefixed Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 10 .1 .3 Seven-Bit Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311 10 .1 .4 HLA Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312 10 .1 .5 Descriptor-Based Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315 10 .2 Static, Pseudo-Dynamic, and Dynamic Strings . . . . . . . . . . . . . . . . . . . . . . . . 316 10 .2 .1 Static Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 10 .2 .2 Pseudo-Dynamic Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 10 .2 .3 Dynamic Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 10 .3 Reference Counting for Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 10 .4 Delphi Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318 10 .5 Using Strings in a High-Level Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319 10 .6 Unicode Character Data in Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321 10 .6 .1 The Unicode Character Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
📄 Page 16
xiv 10 .6 .2 Unicode Code Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322 10 .6 .3 Unicode Code Planes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322 10 .6 .4 Surrogate Code Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 10 .6 .5 Glyphs, Characters, and Grapheme Clusters . . . . . . . . . . . . . . . . . 323 10 .6 .6 Unicode Normals and Canonical Equivalence . . . . . . . . . . . . . . . . 326 10 .6 .7 Unicode Encodings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 10 .6 .8 Unicode Combining Characters . . . . . . . . . . . . . . . . . . . . . . . . . . 328 10 .7 Unicode String Functions and Performance . . . . . . . . . . . . . . . . . . . . . . . . . . 330 10 .8 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 11 RECORD, UNION, AND CLASS DATA TYPES 331 11 .1 Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 11 .1 .1 Declaring Records in Various Languages . . . . . . . . . . . . . . . . . . . 332 11 .1 .2 Instantiating a Record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336 11 .1 .3 Initializing Record Data at Compile Time . . . . . . . . . . . . . . . . . . . 342 11 .1 .4 Storing Records in Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347 11 .1 .5 Using Records to Improve Memory Performance . . . . . . . . . . . . . . 350 11 .1 .6 Working with Dynamic Record Types and Databases . . . . . . . . . . . 351 11 .2 Discriminant Unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351 11 .2 .1 Declaring Unions in Various Languages . . . . . . . . . . . . . . . . . . . . 352 11 .2 .2 Storing Unions in Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 11 .2 .3 Using Unions in Other Ways . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 11 .3 Variant Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 11 .4 Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361 11 .5 Classes and Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 11 .5 .1 Classes vs . Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 11 .5 .2 Simple Class Declarations in C++ . . . . . . . . . . . . . . . . . . . . . . . . 363 11 .5 .3 Class Declarations in C# and Java . . . . . . . . . . . . . . . . . . . . . . . . 366 11 .5 .4 Class Declarations in Delphi (Object Pascal) . . . . . . . . . . . . . . . . . 367 11 .5 .5 Class Declarations in HLA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 11 .5 .6 Virtual Method Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 11 .5 .7 Abstract Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371 11 .5 .8 Sharing VMTs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371 11 .5 .9 Inheritance in Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372 11 .5 .10 Polymorphism in Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 11 .5 .11 Multiple Inheritance (in C++) . . . . . . . . . . . . . . . . . . . . . . . . . . . 376 11 .6 Protocols and Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378 11 .7 Classes, Objects, and Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381 11 .8 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382 12 ARITHMETIC AND LOGICAL EXPRESSIONS 385 12 .1 Arithmetic Expressions and Computer Architecture . . . . . . . . . . . . . . . . . . . . . 386 12 .1 .1 Stack-Based Machines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386 12 .1 .2 Accumulator-Based Machines . . . . . . . . . . . . . . . . . . . . . . . . . . . 391 12 .1 .3 Register-Based Machines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 12 .1 .4 Typical Forms of Arithmetic Expressions . . . . . . . . . . . . . . . . . . . . 394 12 .1 .5 Three-Address Architectures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
📄 Page 17
xv 12 .1 .6 Two-Address Architectures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 12 .1 .7 Architectural Differences and Your Code . . . . . . . . . . . . . . . . . . . 395 12 .1 .8 Complex Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396 12 .2 Optimization of Arithmetic Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 12 .2 .1 Constant Folding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 12 .2 .2 Constant Propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400 12 .2 .3 Dead Code Elimination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404 12 .2 .4 Common Subexpression Elimination . . . . . . . . . . . . . . . . . . . . . . . 410 12 .2 .5 Strength Reduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417 12 .2 .6 Induction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422 12 .2 .7 Loop Invariants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427 12 .2 .8 Optimizers and Programmers . . . . . . . . . . . . . . . . . . . . . . . . . . . 429 12 .3 Side Effects in Arithmetic Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430 12 .4 Containing Side Effects: Sequence Points . . . . . . . . . . . . . . . . . . . . . . . . . . . 434 12 .5 Avoiding Problems Caused by Side Effects . . . . . . . . . . . . . . . . . . . . . . . . . . 438 12 .6 Forcing a Particular Order of Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439 12 .7 Short-Circuit Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441 12 .7 .1 Using Short-Circuit Evaluation with Boolean Expressions . . . . . . . . . 441 12 .7 .2 Forcing Short-Circuit or Complete Boolean Evaluation . . . . . . . . . . 443 12 .7 .3 Comparing Short-Circuit and Complete Boolean Evaluation Efficiency 445 12 .8 The Relative Cost of Arithmetic Operations . . . . . . . . . . . . . . . . . . . . . . . . . . 449 12 .9 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450 13 CONTROL STRUCTURES AND PROGRAMMATIC DECISIONS 451 13 .1 How Control Structures Affect a Program’s Efficiency . . . . . . . . . . . . . . . . . . . 452 13 .2 Introduction to Low-Level Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . 452 13 .3 The goto Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455 13 .3 .1 Restricted Forms of the goto Statement . . . . . . . . . . . . . . . . . . . . . 459 13 .4 The if Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460 13 .4 .1 Improving the Efficiency of Certain if/else Statements . . . . . . . . . . . 463 13 .4 .2 Forcing Complete Boolean Evaluation in an if Statement . . . . . . . . . 465 13 .4 .3 Forcing Short-Circuit Evaluation in an if Statement . . . . . . . . . . . . . 471 13 .5 The switch/case Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476 13 .5 .1 Semantics of a switch/case Statement . . . . . . . . . . . . . . . . . . . . . 477 13 .5 .2 Jump Tables vs . Chained Comparisons . . . . . . . . . . . . . . . . . . . . . 478 13 .5 .3 Other Implementations of switch/case . . . . . . . . . . . . . . . . . . . . . 485 13 .5 .4 The Swift switch Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500 13 .5 .5 Compiler Output for switch Statements . . . . . . . . . . . . . . . . . . . . . 501 13 .6 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501 14 ITERATIVE CONTROL STRUCTURES 503 14 .1 The while Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504 14 .1 .1 Forcing Complete Boolean Evaluation in a while Loop . . . . . . . . . . 506 14 .1 .2 Forcing Short-Circuit Boolean Evaluation in a while Loop . . . . . . . . 515 14 .2 The repeat . .until (do . .until/do . .while) Loop . . . . . . . . . . . . . . . . . . . . . . . . . . 518 14 .2 .1 Forcing Complete Boolean Evaluation in a repeat . .until Loop . . . . . 521 14 .2 .2 Forcing Short-Circuit Boolean Evaluation in a repeat . .until Loop . . . . 524
📄 Page 18
xvi 14 .3 The forever . .endfor Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529 14 .3 .1 Forcing Complete Boolean Evaluation in a forever Loop . . . . . . . . . 532 14 .3 .2 Forcing Short-Circuit Boolean Evaluation in a forever Loop . . . . . . . 532 14 .4 The Definite Loop (for Loops) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532 14 .5 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534 15 FUNCTIONS AND PROCEDURES 535 15 .1 Simple Function and Procedure Calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536 15 .1 .1 Return Address Storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 15 .1 .2 Other Sources of Overhead . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544 15 .2 Leaf Functions and Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545 15 .3 Macros and Inline Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549 15 .4 Passing Parameters to a Function or Procedure . . . . . . . . . . . . . . . . . . . . . . . 556 15 .5 Activation Records and the Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563 15 .5 .1 Breaking Down the Activation Record . . . . . . . . . . . . . . . . . . . . . . 565 15 .5 .2 Assigning Offsets to Local Variables . . . . . . . . . . . . . . . . . . . . . . . 568 15 .5 .3 Associating Offsets with Parameters . . . . . . . . . . . . . . . . . . . . . . . 570 15 .5 .4 Accessing Parameters and Local Variables . . . . . . . . . . . . . . . . . . 575 15 .5 .5 Registers to the Rescue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585 15 .5 .6 Java VM and Microsoft CLR Parameters and Locals . . . . . . . . . . . . 587 15 .6 Parameter-Passing Mechanisms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588 15 .6 .1 Pass-by-Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588 15 .6 .2 Pass-by-Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 589 15 .7 Function Return Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590 15 .8 For More Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 597 AFTERWORD: ENGINEERING SOFTWARE 599 GLOSSARY 601 ONLINE APPENDIXES 607 INDEX 609
📄 Page 19
A C K N O W L E D G M E N T S Many people have read and reread every word, symbol, and punctuation mark in this book in order to produce a better result. Kudos to the follow- ing people for their careful work on the second edition: development editor Athabasca Witschi, copyeditor/production editor Rachel Monaghan, and proofreader James Fraleigh. I would like to take the opportunity to graciously thank Anthony Tribelli, a longtime friend, who went well beyond the call of duty when doing a technical review of this book. He pulled every line of code out of this book (including snippets) and compiled and ran it to make sure it worked properly. His suggestions and opinions throughout the technical review process have dramatically improved the quality of this work. Of course, I would also like to thank all the countless readers over the years who’ve emailed suggestions and corrections, many of which have found their way into this second edition. Thanks to all of you, Randall Hyde
📄 Page 20
(This page has no text content)
The above is a preview of the first 20 pages. Register to read the complete e-book.

💝 Support Author

0.00
Total Amount (¥)
0
Donation Count

Login to support the author

Login Now
Back to List