ebook img

Fluent C: Principles, Practices, and Patterns PDF

306 Pages·2022·7.268 MB·English
Save to my drive
Quick download
Download
Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.

Preview Fluent C: Principles, Practices, and Patterns

Fluent C FF ll uu Principles, Practices, and Patterns ee nn tt CC P r e s c h e r n Christopher Preschern Fluent C FF Expert advice on C programming is hard to find. While much ll help is available for object-oriented programming languages, “Full of real-world uu there’s surprisingly little for the C language. With this hands- examples, Fluent C is on guide, beginners and experienced C programmers alike ee an excellent resource will find guidance about design decisions, including how to apply them bit by bit to running code examples when building for making your code nn large-scale programs. cleaner and more tt Christopher Preschern, a leading member of the design maintainable.” patterns community, answers questions about how to — David Griffiths CC structure C programs, cope with error handling, and design Author of Head First C flexible interfaces. Whether you’re looking for one particular ”This book guides pattern or an overview of design options for a specific topic, this book shows you the way. In Part I, you’ll learn how to novices toward making implement hands-on design knowledge specifically for the C industrial-strength programming language. products in C.” Part II includes stories of applying C programming patterns to implement larger programs. You’ll learn how patterns can —Robert Hanmer make your life easier through good design decisions. This Software Architect book includes patterns for: • Error handling Christopher Preschern organizes • Returning error information design pattern conferences and initiatives to improve pattern writing. • Memory management As a C programmer at the company • Returning data from C functions ABB, he gathered and documented hands-on knowledge on how to write • Data lifetime and ownership industrial-strength code. He has • Flexible APIs lectured on coding and quality at Graz University of Technology and holds a • Flexible iterator interfaces PhD in computer science. P r • Organizing files in modular programs e s c • Escaping #ifdef hell h e r n C / PROGRAMMING LANGUAGES Twitter: @oreillymedia linkedin.com/company/oreilly-media US $59.99 CAN $74.99 youtube.com/oreillymedia ISBN: 978-1-492-109733-4 Fluent C Principles, Practices, and Patterns Christopher Preschern BBeeiijjiinngg BBoossttoonn FFaarrnnhhaamm SSeebbaassttooppooll TTookkyyoo Fluent C by Christopher Preschern Copyright © 2023 Christopher Preschern. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (https://oreilly.com). For more information, contact our corporate/institu‐ tional sales department: 800-998-9938 or [email protected]. Acquisitions Editor: Brian Guerin Indexer: Judith McConville Development Editor: Corbin Collins Interior Designer: David Futato Production Editor: Jonathon Owen Cover Designer: Karen Montgomery Copyeditor: Piper Editorial Consulting, LLC Illustrator: Kate Dullea Proofreader: Justin Billing October 2022: First Edition Revision History for the First Edition 2022-10-14: First Release See https://oreilly.com/catalog/errata.csp?isbn=9781492097334 for release details. The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Fluent C, the cover image, and related trade dress are trademarks of O’Reilly Media, Inc. The views expressed in this work are those of the author and do not represent the publisher’s views. While the publisher and the author have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the author disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights. 978-1-492-09733-4 [LSI] Table of Contents Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii Part I. C Patterns 1. Error Handling. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Running Example 5 Function Split 6 Guard Clause 9 Samurai Principle 12 Goto Error Handling 16 Cleanup Record 19 Object-Based Error Handling 22 Summary 26 Further Reading 27 Outlook 27 2. Returning Error Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Running Example 30 Return Status Codes 32 Return Relevant Errors 39 Special Return Values 45 Log Errors 48 Summary 55 Further Reading 55 Outlook 56 iii 3. Memory Management. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Data Storage and Problems with Dynamic Memory 59 Running Example 61 Stack First 62 Eternal Memory 65 Lazy Cleanup 69 Dedicated Ownership 72 Allocation Wrapper 76 Pointer Check 81 Memory Pool 84 Summary 90 Further Reading 90 Outlook 91 4. Returning Data from C Functions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Running Example 94 Return Value 95 Out-Parameters 99 Aggregate Instance 103 Immutable Instance 108 Caller-Owned Buffer 111 Callee Allocates 116 Summary 120 Outlook 120 5. Data Lifetime and Ownership. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Stateless Software-Module 123 Software-Module with Global State 127 Caller-Owned Instance 132 Shared Instance 138 Summary 144 Further Reading 145 Outlook 145 6. Flexible APIs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 Header Files 149 Handle 152 Dynamic Interface 156 Function Control 159 Summary 163 Further Reading 163 Outlook 164 iv | Table of Contents 7. Flexible Iterator Interfaces. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Running Example 167 Index Access 168 Cursor Iterator 172 Callback Iterator 177 Summary 182 Further Reading 183 Outlook 183 8. Organizing Files in Modular Programs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Running Example 187 Include Guard 189 Software-Module Directories 192 Global Include Directory 197 Self-Contained Component 201 API Copy 207 Summary 216 Outlook 216 9. Escaping #ifdef Hell. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Running Example 219 Avoid Variants 220 Isolated Primitives 224 Atomic Primitives 227 Abstraction Layer 231 Split Variant Implementations 236 Summary 242 Further Reading 243 Outlook 243 Part II. Pattern Stories 10. Implementing Logging Functionality. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 The Pattern Story 247 File Organization 248 Central Logging Function 249 Logging Source Filter 250 Conditional Logging 252 Multiple Logging Destinations 253 File Logging 254 Cross-Platform Files 255 Table of Contents | v Using the Logger 259 Summary 259 11. Building a User Management System. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 The Pattern Story 261 Data Organization 261 File Organization 263 Authentication: Error Handling 264 Authentication: Error Logging 266 Adding Users: Error Handling 267 Iterating 269 Using the User Management System 272 Summary 272 12. Conclusion. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 What You’ve Learned 275 Further Reading 275 Closing Remarks 276 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 vi | Table of Contents Preface You picked up this book to move your programming skills one step forward. That is good, because you’ll definitely benefit from the hands-on knowledge provided in this book. If you have a lot of experience programming in C, you’ll learn the details of good design decisions and about their benefits and drawbacks. If you are fairly new to C programming, you’ll find guidance about design decisions, and you’ll see how these decisions are applied bit by bit to running code examples for building larger scale programs. The book answers questions such as how to structure a C program, how to cope with error handling, or how to design flexible interfaces. As you learn more about C pro‐ gramming, questions often pop up, such as the following: • Should I return any error information I have? • Should I use the global variable errno to do that? • Should I have few functions with many parameters or the other way around? • How do I build a flexible interface? • How can I build basic things like an iterator? For object-oriented languages, most of these questions are answered to a great extent by the Gang of Four book Design Patterns: Elements of Reusable Object-Oriented Soft‐ ware by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Prentice Hall, 1997). Design patterns provide a programmer with best practices on how objects should interact and which object owns which other kinds of objects. Also, design patterns show how such objects can be grouped together. However, for procedural programming languages like C, most of these design pat‐ terns cannot be implemented in the way described by the Gang of Four. There are no native object-oriented mechanisms in C. It is possible to emulate inheritance or poly‐ morphism in the C programming language, but that might not be the first choice, because such emulation makes things unfamiliar for programmers who are used to vii programming C and are not used to programming with object-oriented languages like C++ and using concepts like inheritance and polymorphism. Such programmers may want to stick to their native C programming style that they are used to. However, with the native C programming style, not all object-oriented design patterns guidance is usable, or at least the specific implementation of the idea presented in a design pat‐ tern is not provided for non-object-oriented programming languages. And that is where we stand: we want to program in C, but we cannot directly use most of the knowledge documented in design patterns. This book shows how to bridge this gap and implement hands-on design knowledge for the C programming language. Why I Wrote This Book Let me tell you why the knowledge gathered in this book turned out to be very important for me and why such knowledge is hard to find. In school I learned C programming as my first programming language. Just like every new C programmer, I wondered why arrays start with index 0, and I first rather ran‐ domly tried out how to place the operators * and & in order to finally get the C pointer magic working. At university I learned how C syntax actually works and how it translates to bits and bytes on the hardware. With that knowledge I was able to write small programs that worked very well. However, I still had trouble understanding why longer code looked the way it did, and I certainly wouldn’t have come up with solutions like the following: typedef struct INTERNAL_DRIVER_STRUCT* DRIVER_HANDLE; typedef void (*DriverSend_FP)(char byte); typedef char (*DriverReceive_FP)(); typedef void (*DriverIOCTL_FP)(int ioctl, void* context); struct DriverFunctions { DriverSend_FP fpSend; DriverReceive_FP fpReceive; DriverIOCTL_FP fpIOCTL; }; DRIVER_HANDLE driverCreate(void* initArg, struct DriverFunctions f); void driverDestroy(DRIVER_HANDLE h); void sendByte(DRIVER_HANDLE h, char byte); char receiveByte(DRIVER_HANDLE h); void driverIOCTL(DRIVER_HANDLE h, int ioctl, void* context); viii | Preface

See more

The list of books you might like

Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.