Effective C: An Introduction to Professional C Programming

Effective C: An Introduction to Professional C Programming

by Robert C. Seacord
Effective C: An Introduction to Professional C Programming

Effective C: An Introduction to Professional C Programming

by Robert C. Seacord

Paperback

$49.99 
  • SHIP THIS ITEM
    Qualifies for Free Shipping
  • PICK UP IN STORE
    Check Availability at Nearby Stores

Related collections and offers


Overview

A detailed introduction to the C programming language for experienced programmers.

The world runs on code written in the C programming language, yet most schools begin the curriculum with Python or Java. Effective C bridges this gap and brings C into the modern era—covering the modern C17 Standard as well as potential C2x features. With the aid of this instant classic, you'll soon be writing professional, portable, and secure C programs to power robust systems and solve real-world problems.

Robert C. Seacord introduces C and the C Standard Library while addressing best practices, common errors, and open debates in the C community. Developed together with other C Standards committee experts, Effective C will teach you how to debug, test, and analyze C programs. You'll benefit from Seacord's concise explanations of C language constructs and behaviors, and from his 40 years of coding experience.

You'll learn:
  • How to identify and handle undefined behavior in a C program
  • The range and representations of integers and floating-point values
  • How dynamic memory allocation works and how to use nonstandard functions
  • How to use character encodings and types
  • How to perform I/O with terminals and filesystems using C Standard streams and POSIX file descriptors
  • How to understand the C compiler's translation phases and the role of the preprocessor
  • How to test, debug, and analyze C programs

  • Effective C will teach you how to write professional, secure, and portable C code that will stand the test of time and help strengthen the foundation of the computing world.

    Product Details

    ISBN-13: 9781718501041
    Publisher: No Starch Press
    Publication date: 08/04/2020
    Pages: 272
    Sales rank: 415,342
    Product dimensions: 6.90(w) x 9.10(h) x 0.80(d)

    About the Author

    Robert C. Seacord is a Technical Director at NCC Group where he develops and delivers secure coding training in C, C++, and other languages. Seacord is an expert on the C Standards committee. His six previous books include The CERT C Coding Standard and Secure Coding in C and C++.

    Read an Excerpt

    INTRODUCTION

    C was developed as a system programming language in the 1970s, and even after all this time, it remains incredibly popular. System languages are designed for performance and ease of access to the underlying hardware while providing high-level programming features. While other languages may offer newer language features, their compilers and libraries are typically written in C. Carl Sagan once said, “If you wish to make an apple pie from scratch, you must first invent the universe.”

    The inventors of C did not invent the universe; they designed C to work with a variety of computing hardware and architectures that, in turn, were constrained by physics and mathematics. C is layered directly on top of computing hardware, making it more sensitive to evolving hardware features, such as vectorized instructions, than higher-level languages that typically rely on C for their efficiency.

    According to the TIOBE index, C has been either the most popular programming language or second most popular since 2001.1 C is TIOBE’s programming language of the year for 2019. The popularity of the C programming language can most likely be attributed to several tenets of the language referred to as the spirit of C:

    • Trust the programmer. Generally speaking, the C language assumes you know what you’re doing and lets you. This isn’t always a good thing (for example, if you don’t know what you’re doing).
    • Don’t prevent the programmer from doing what needs to be done. Because C is a system programming language, it has to be able to handle a variety of low-level tasks.
    • Keep the language small and simple. The language is designed to be fairly close to the hardware and to have a small footprint.
    • Provide only one way to do an operation. Also known as conservation of mechanism, the C language tries to limit the introduction of duplicate mechanisms.
    • Make it fast, even if it isn’t guaranteed to be portable. Allowing you to write optimally efficient code is the top priority. The responsibility of ensuring that code is portable, safe, and secure is delegated to you, the programmer.

    A Brief History of C

    The C programming language was developed in 1972 by Dennis Ritchie and Ken Thompson at Bell Telephone Laboratories. Brian Kernighan coauthored The C Programming Language (K&R 1988) with Dennis Ritchie. In 1983, the American National Standards Institute (ANSI) formed the X3J11 committee to establish a standard C specification, and in 1989, the C Standard was ratified as ANSI X3.159-1989, “Programming Language C.” This 1989 version of the language is referred to as ANSI C or C89.

    In 1990, the ANSI C Standard was adopted (unchanged) by a joint technical committee of the International Organization for Standardization (ISO) and the International Electrotechnical Commission (IEC) and published as the first edition of the C Standard, C90 (ISO/IEC 9899:1990). The second edition of the C Standard, C99, was published in 1999 (ISO/IEC 9899:1999), and a third edition, C11, in 2011 (ISO/IEC 9899:2011). The latest version of the C Standard (as of this writing) is the fourth version, published in 2018 as C17 (ISO/IEC 9899:2018). A new major revision referred to as C2x is under development by ISO/IEC. According to 2018 polling data from JetBrains, 52 percent of C programmers use C99, 36 percent use C11, and 23 percent use an embedded version of C.2

    The C Standard

    The C Standard (ISO/IEC 9899:2018) defines the language and is the final authority on language behavior. While the standard can be obscure to impenetrable, you need to understand it if you intend to write code that’s portable, safe, and secure. The C Standard provides a substantial degree of latitude to implementations to allow them to be optimally efficient on various hardware platforms. Implementations is the term used by the C Standard to refer to compilers and is defined as follows:

    A particular set of software, running in a particular translation environment under particular control options, that performs translation of programs for, and supports execution of functions in, a particular execution environment.

    This definition indicates that each compiler with a particular set of command line flags, along with the C Standard Library, is considered a separate implementation, and different implementations can have significantly different implementation-defined behavior. This is noticeable in GNU Compiler Collection (GCC), which uses the -std= flag to determine the language standard. Possible values for this option include c89, c90, c99, c11, c17, c18, and c2x. The default depends on the version of the compiler. If no C language dialect options are given, the default for GCC 10 is -std=gnu17, which provides extensions to the C language. For portability, specify the standard you’re using. For access to new language features, specify a recent standard. A good choice (in 2019) with GCC 8 and later is -std=c17.

    Because implementations have such a range of behaviors, and because some of these behaviors are undefined, you can’t understand the C language by just writing simple test programs to examine the behavior. The behavior of the code may vary when compiled by a different implementation on different platforms or even the same implementation using a different set of flags or a different C Standard Library implementation. Code behavior can even vary between versions of a compiler. The C Standard is the only document that specifies which behaviors are guaranteed for all implementations, and where you need to plan for variability. This is mostly a concern when developing portable code, but can also affect the security and safety of your code.

    The CERT C Coding Standard

    The CERT ® C Coding Standard, Second Edition: 98 Rules for Developing Safe, Reliable, and Secure Systems (Seacord 2014) is a reference book I wrote while managing the secure coding team at the Software Engineering Institute at Carnegie Mellon University. The CERT C Coding Standard contains examples of common C programming mistakes and how to correct them. Throughout this book, we reference some of these rules as a source for detailed information on specific C language programming topics.

    Who This Book Is For

    This book is an introduction to the C language. It is written to be as accessible as possible to anyone who wants to learn C programming, without dumbing it down. In other words, we didn’t overly simplify C programming in the way many other introductory books and courses might. These overly simplified references will teach you how to get code to compile and run, but the code might still be wrong. Developers who learn how to program C from such sources will typically develop substandard, flawed, insecure code that will eventually need to be rewritten (often sooner than later). Hopefully, these developers will eventually benefit from senior developers in their organizations who will help them unlearn these harmful misconceptions about programming in C, and help them start developing professional quality C code. On the other hand, this book will quickly teach you how to develop correct, portable, professional-quality code, build a foundation for developing security-critical and safety-critical systems, and perhaps teach you a thing or two that even the senior developers at your organization don’t know.

    Effective C: An Introduction to Professional C Programming is a concise introduction to essential C language programming that will soon have you writing programs, solving problems, and building working systems. The code examples are idiomatic and straightforward. In this book, you’ll learn about essential programming concepts in C and practice writing high-quality code with exercises for each topic. You’ll also learn about good software engineering practices for developing correct, secure C code.  

    What’s in This Book

    This book starts with an introductory chapter that covers just enough material to get you programming right from the start. After this, we circle back and examine the basic building blocks of the language. The book culminates with two chapters that will show you how to compose real-world systems from these basic building blocks and how to debug, test, and analyze the code you’ve written. The chapters are as follows:

    Chapter 1: Getting Started with C  You’ll write a simple C program to become familiar with using the main function. You’ll also look at a few options for editors and compilers.

    Chapter 2: Objects, Functions, and Types  This chapter explores basics like declaring variables and functions. You’ll also look into the principles of using basic types.

    Chapter 3: Arithmetic Types  You’ll learn about the two kinds of arithmetic data types: integers and floating-point types.

    Chapter 4: Expressions and Operators  You’ll learn about operators and how to write simple expressions to perform operations on various object types.

    Chapter 5: Control Flow  You’ll learn how to control the order in which individual statements are evaluated. We’ll start by going over expression statements and compound statements that define the work to be performed. We’ll then cover three kinds of statements that determine which code blocks are executed, and in what order: selection, iteration, and jump statements.

    Chapter 6: Dynamically Allocated Memory  You’ll learn about dynamically allocated memory, which is allocated from the heap at runtime. Dynamically allocated memory is useful when the exact storage requirements for a program are unknown before runtime.

    Chapter 7: Character and Strings  You’ll learn about the various character sets, including ASCII and Unicode, that can be used to compose strings. You’ll learn how strings are represented and manipulated using the legacy functions from the C Standard Library, the bounds-checking interfaces, and POSIX and Windows APIs.

    Chapter 8: Input/Output  This chapter will teach you how to perform input/output (I/O) operations to read data from, or write data to, terminals and filesystems. I/O involves all the ways information enters or exits a program, without which your programs would be useless. We’ll cover techniques that make use of C Standard streams and POSIX file descriptors.

    Chapter 9: Preprocessor  You’ll learn how to use the preprocessor to include files, define object- and function-like macros, and conditionally include code based on implementation-specific features.

    Chapter 10: Program Structure  You’ll learn how to structure your program into multiple translation units consisting of both source and include files. You’ll also learn how to link multiple object files together to create libraries and executable files. 

    Chapter 11: Debugging, Testing, and Analysis  This chapter describes tools and techniques for producing correct programs, including compiletime and runtime assertions, debugging, testing, static analysis, and dynamic analysis. The chapter also discusses which compiler flags are recommended for use in different phases of the software development process.

    You’re about to embark on a journey from which you will emerge a newly minted but professional C developer

    Table of Contents

    Foreword Pascal Cuoq xvii

    Foreword Ollie Whitehouse xix

    Acknowledgments xxi

    Introduction xxiii

    A Brief History of C xxiv

    The C Standard xxv

    The CERT C Coding Standard xxvi

    Who This Book Is For xxvi

    What's in This Book xxvi

    1 Getting Started With C 1

    Developing Your First C Program 1

    Compiling and Running Your Program 2

    Preprocessor Directives 3

    The main Function 3

    Checking Function Return Values 5

    Formatted Output 5

    Editors and Integrated Development Environments 6

    Compilers 8

    GNU Compiler Collection 8

    Clang 8

    Microsoft Visual Studio 9

    Portability 9

    Implementation-Defined Behavior 10

    Unspecified Behavior 10

    Undefined Behavior 10

    Locale-Specific Behavior and Common Extensions 11

    Summary 11

    2 Objects, Functions, and Types 13

    Objects, Functions, Types, and Pointers 13

    Declaring Variables 14

    Swapping Values (First Attempt) 15

    Swapping Values (Second Attempt) 16

    Scope 18

    Storage Duration 19

    Alignment 20

    Object Types 21

    Boolean Types 21

    Character Types 22

    Numerical types 22

    Void Types 24

    Function Types 24

    Derived Types 25

    Pointer Types 25

    Arrays 26

    Structures 28

    Unions 29

    Tags 30

    Type Qualifiers 32

    Const 32

    Volatile 33

    Restrict 33

    Exercises 34

    Summary 34

    3 Arithmetic Types 35

    Integers 36

    Padding and Precision 36

    The <limits.h> Header File 36

    Declaring Integers 37

    Unsigned Integers 37

    Signed Integers 40

    Integer Constants 44

    Floating-Point 45

    Floating-Point Types 46

    Floating-Point Arithmetic 47

    Floating-Point Values 47

    Floating-Point Constants 49

    Arithmetic Conversion 49

    Integer Conversion Rank 50

    Integer Promotions 51

    Usual Arithmetic Conversions 52

    An Example of Implicit Conversion 53

    Safe Conversions 54

    Summary 55

    4 Expressions and Operators 57

    Simple Assignment 58

    Evaluations 59

    Function Invocation 60

    Increment and Decrement Operators 61

    Operator Precedence and Associativity 62

    Order of Evaluation 64

    Unsequenced and Indeterminately Sequenced Evaluations 65

    Sequence Points 66

    Sizeof Operator 66

    Arithmetic Operators 67

    Unary + and - Operators 67

    Logical Negation Operator 68

    Multiplicative Operators 68

    Additive Operators 69

    Bitwise Operators 69

    Complement Operator 70

    Shift Operators 70

    Bitwise AND Operator 72

    Bitwise Exclusive OR Operator 72

    Bitwise Inclusive OR Operator 73

    Logical Operators 73

    Cast Operators 75

    Conditional Operator 76

    _Alignof Operator 76

    Relational Operators 77

    Compound Assignment Operators 78

    Comma Operator 78

    Pointer Arithmetic 79

    Summary 80

    5 Control Flow 81

    Expression Statements 81

    Compound Statements 82

    Selection Statements 83

    The if Statement 83

    The switch Statement 86

    Iteration Statements 89

    The while Statement 89

    The do…while Statement 90

    The for Statement 91

    Jump Statements 93

    The goto Statement 93

    The continue Statement 94

    The break Statement 95

    The return Statement 96

    Exercises 97

    Summary 97

    6 Dynamically Allocated Memory 99

    Storage Duration 100

    The Heap and Memory Managers 100

    When to Use Dynamically Allocated Memory 101

    Memory Management Functions 101

    The malloc Function 102

    The aligned_alloc Function 104

    The calloc Function 105

    The realloc Function 105

    The reallocarray Function 107

    The free Function 108

    Memory States 109

    Flexible Array Members 110

    Other Dynamically Allocated Storage 111

    The alloca Function 111

    Variable-Length Arrays 112

    Debugging Allocated Storage Problems 115

    Dmalloc 116

    Safety-Critical Systems 118

    Exercises 118

    Summary 118

    7 Characters and Strings 119

    Characters 120

    ASCII 120

    Unicode 120

    Source and Execution Character Sets 122

    Data Types 122

    Character Constants 124

    Escape Sequences 125

    Linux 126

    Windows 126

    Character Conversion 128

    Strings 131

    String Literals 132

    String-Handling Functions 134

    <String.h> and <wchar.h> 135

    Annex K Bounds-Checking Interfaces 141

    POSIX 144

    Microsoft 145

    Summary 145

    8 Input/Output 147

    Standard I/O Streams 148

    Stream Buffering 148

    Predefined Streams 149

    Stream Orientation 150

    Text and Binary Streams 150

    Opening and Creating Files 151

    The fopen Function 151

    The POSIX open Function 153

    Closing Files 154

    The fclose Function 154

    The POSIX close Function 155

    Reading and Writing Characters and Lines 155

    Stream Flushing 157

    Setting the Position in a File 158

    Removing and Renaming Files 161

    Using Temporary Files 161

    Reading Formatted Text Streams 162

    Reading to and Writing from Binary Streams 165

    Summary 168

    9 Preprocessor 169

    The Compilation Process 170

    File Inclusion 171

    Quoted and Angle Bracket Include Strings 172

    Conditional Inclusion 172

    Generating Errors 173

    Using Header Guards 174

    Macro Definitions 175

    Macro Replacement 178

    Type-Generic Macros 180

    Predefined Macros 181

    Summary 183

    10 Program Structure 185

    Principles of Componentization 186

    Coupling and Cohesion 186

    Code Reuse 187

    Data Abstractions 187

    Opaque Types 188

    Executables 189

    Linkage 191

    Structuring a Simple Program 192

    Building the Code 196

    Summary 198

    11 Debugging, Testing, and Analysis 199

    Assertions 199

    Static Assertions 200

    Runtime Assertions 202

    Compiler Settings and Flags 203

    GCC and Clang 204

    Visual C++ 206

    Debugging 208

    Unit Testing 211

    Static Analysis 214

    Dynamic Analysis 216

    AddressSanitizer 217

    Exercises 221

    Summary 221

    References 223

    Index 227

    From the B&N Reads Blog

    Customer Reviews