Page
1
M A N N I N G Jens Gustedt
Page
2
Modern C JENS GUSTEDT M A N N I N G SHELTER ISLAND
Page
3
For online information and ordering of this and other Manning books, please visit www.manning.com. The publisher offers discounts on this book when ordered in quantity. For more information, please contact Special Sales Department Manning Publications Co. 20 Baldwin Road PO Box 761 Shelter Island, NY 11964 Email: orders@manning.com © 2020 Jens Gustedt has released the manuscript of this work under a Creative Commons license for non-commercial use (CC BY NC). Jens Gustedt has granted to Manning Publications the exclusive commercial right to publish this work in print and electronic formats throughout the world. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the book, and Manning Publications was aware of a trademark claim, the desig- nations have been printed in initial caps or all caps. ∞ Recognizing the importance of preserving what has been written, it is Mannings policy to have the books we publish printed on acid-free paper, and we exert our best efforts to that end. Recognizing also our responsibility to conserve the resources of our planet, Manning books are printed on paper that is at least 15 percent recycled and processed without the use of elemental chlorine. Manning Publications Co. 20 Baldwin Road PO Box 761 Shelter Island, NY 11964 Acquisitions editor: Mike Stephens Development editor: Jennifer Stout Technical development editor: Jon Bergman Review editor: Aleksander Dragosavljevic Technical proofreader: Nitin Gode Cover designer: Marija Tudor ISBN 9781617295812 Printed in the United States of America
Page
4
Contents Acknowledgments ix About this book xi About the cover illustration xvi Level 0 Encounter . ....................................................................... 1 1 Getting started 3 1.1 Imperative programming 4 1.2 Compiling and running 5 2 The principal structure of a program 11 2.1 Grammar 11 2.2 Declarations 13 2.3 Definitions 15 2.4 Statements 17 Iteration 17 Function calls 18 Function return 19 iii
Page
5
iv Contents Level 1 Acquaintance . ................................................................ 21 3 Everything is about control 27 3.1 Conditional execution 28 3.2 Iterations 30 3.3 Multiple selection 34 4 Expressing computations 37 4.1 Arithmetic 40 +, -, and * 40 Division and remainder 41 4.2 Operators that modify objects 42 4.3 Boolean context 43 Comparison 43 Logic 44 4.4 The ternary or conditional operator 45 4.5 Evaluation order 45 5 Basic values and data 49 5.1 The abstract state machine 50 Values 52 Types 52 Binary representation and the abstract state machine 52 Optimization 53 5.2 Basic types 54 5.3 Specifying values 57 Complex constants 61 5.4 Implicit conversions 61 5.5 Initializers 64 5.6 Named constants 65 Read-only objects 66 Enumerations 67 Macros 68 Compound literals 69 5.7 Binary representions 70 Unsigned integers 70 Bit sets and bitwise operators 71 Shift operators 73 Boolean values 74 Signed integers 74 Fixed-width integer types 77 Floating- point data 78
Page
6
v 6 Derived data types 81 6.1 Arrays 82 Array declaration 82 Array operations 83 Array length 83 Arrays as parameters 85 Strings are special 85 6.2 Pointers as opaque types 89 6.3 Structures 91 6.4 New names for types: type aliases 96 7 Functions 99 7.1 Simple functions 100 7.2 main is special 102 7.3 Recursion 104 8 C library functions 113 8.1 General properties of theC library and its functions 113 Headers 114 Interfaces 114 Error checking 116 Bounds-checking interfaces 117 Platform preconditions 118 8.2 Mathematics 119 8.3 Input, output, and filemanipulation 121 Unformatted text output 121 Files and streams 123 Text IO 125 Formatted output 127 Unformatted text input 130 8.4 String processing and conversion 132 8.5 Time 136 8.6 Runtime environment settings 141 8.7 Program termination and assertions 143 Level 2 Cognition ...................................................................... 147 9 Style 149 9.1 Formatting 150 9.2 Naming 151
Page
7
vi Contents 10 Organization and documentation 157 10.1 Interface documentation 158 10.2 Implementation 161 Macros 162 Pure functions 164 11 Pointers 169 11.1 Pointer operations 170 Address-of and object-of operators 170 Pointer addition 171 Pointer subtraction and difference 173 Pointer validity 175 Null pointers 177 11.2 Pointers and structures 178 11.3 Pointers and arrays 182 Array and pointer access are the same 182 Array and pointer parameters are the same 182 11.4 Function pointers 184 12 The C memory model 191 12.1 A uniform memory model 193 12.2 Unions 193 12.3 Memory and state 195 12.4 Pointers to unspecific objects 197 12.5 Explicit conversions 198 12.6 Effective types 199 12.7 Alignment 200 13 Storage 205 13.1 malloc and friends 206 A complete example with varying array size 207 Ensuring consistency of dynamic allocations 215 13.2 Storage duration, lifetime, and visibility 215 Static storage duration 219 Automatic storage duration 220 13.3 Digression: using objects ”before” their definition 221
Page
8
vii 13.4 Initialization 223 13.5 Digression: a machine model 225 14 More involved processing and IO 231 14.1 Text processing 231 14.2 Formatted input 238 14.3 Extended character sets 239 14.4 Binary streams 247 14.5 Error checking and cleanup 249 Level 3 Experience . ................................................................... 255 15 Performance 257 15.1 Inline functions 260 15.2 Using restrict qualifiers 263 15.3 Measurement and inspection 265 16 Function-like macros 275 16.1 How function-like macros work 277 16.2 Argument checking 279 16.3 Accessing the calling context 282 16.4 Default arguments 285 16.5 Variable-length argument lists 286 Variadic macros 287 A detour: variadic functions 291 16.6 Type-generic programming 294 17 Variations in control f low 301 17.1 A complicated example 303 17.2 Sequencing 305 17.3 Short jumps 308 17.4 Functions 309 17.5 Long jumps 310
Page
9
viii Contents 17.6 Signal handlers 315 18 Threads 325 18.1 Simple inter-thread control 328 18.2 Race-free initialization and destruction 330 18.3 Thread-local data 333 18.4 Critical data and critical sections 333 18.5 Communicating through condition variables 336 18.6 More sophisticated threadmanagement 341 19 Atomic access and memory consistency 345 19.1 The “happened before” relation 347 19.2 C library calls that provide synchronization 349 19.3 Sequential consistency 352 19.4 Other consistency models 353 Takeaways 357 Bibliography 370 Index 372
Page
10
Acknowledgments Special thanks go to the people that encouraged the writing of this book by providing me with constructive feedback, including colleagues and other interested readers, Cédric Bastoul, Lucas Nussbaum, Vincent Loech- ner, Kliment Yanev, Szabolcs Nagy, Marcin Kowalczuk, Ali Asad Lotia, Richard Palme, Yann Barsamian, Fernando Oleo, Róbert Kohányi, Jean-Michel Gorius ... Manning’s staff Jennifer Stout, Nitin Gode and Tiffany Taylor, ... ... and the impressive number of reviewers provided by Manning: Adam Kalisz, Andrei de Araujo Formiga, Christoph Schubert, Erick Nogueira do Nascimento, Ewelina Sowka, Glen Sirakavit, Hugo Durana, Jean-François Morin, Kent R. Spillner, Louis Aloia, Manu Raghavan Sareena, Nitin Gode, Rafael Aiquel, Sanchir Kartiev, and Xavier Barthel Many others have contributed to the success of this book, my sincerest thanks to all of you. ix
Page
11
(This page has no text content)
Page
12
About this book The C programming language has been around for a long time — the canonical reference for it is the book written by its creators, Kernighan and Ritchie [1978]. Since then, C has been used in an incredible number of applications. Programs and systems written in C are all around us: in personal computers, phones, cameras, set-top boxes, refrigerators, cars, mainframes, satellites ... basically in any modern device that has a programmable interface. In contrast to the ubiquitous presence of C programs and systems, good knowledge of and about C is much more scarce. Even experienced C programmers often appear to be stuck in some degree of self-inflicted ignorance about the modern evolution of the C language. A likely reason for this is that C is seen as an "easy to learn" language, allowing a programmer with little experience to quickly write or copy snippets of code that at least appear to do what it’s supposed to. In a way, C fails to motivate its users to climb to higher levels of knowledge. This book is intended to change that general attitude, so it is organized in levels that reflect familiarity with the C language and programming in general. This structure may go against some habits of the book’s readers; in particular, it splits some difficult subjects (such as point- ers) across levels in order to not swamp readers too early with the wrong information. We’ll explain the book’s organization in more detail shortly. Generally, although many universally applicable ideas will be presented, that would also be valid for other programming languages (such as Java, Python, Ruby, C#, or C++) the book primarily addresses concepts and practices that are unique to C or are of particular value when programming in the C language. C versions As the title of this book suggests, today’s C is not the same language as the one originally designed by its creators, Kernighan and Ritchie (usually referred to as K&R C). In particular, xi
Page
13
xii ABOUT THIS BOOK it has undergone an important standardization and extension process, now driven by ISO, the International Standards Organization. This led to the publication of a series of C standards in 1989, 1999, 2011, and 2018, commonly referred to as C89, C99, C11, and C17. The C standards committee puts a lot of effort into guaranteeing backward compatibility such that code written for earlier versions of the language, say C89, should compile to a semantically equivalent executable with a compiler that implements a newer version. Unfortunately, this backward compatibility has had the unwanted side effect of not motivating projects that could benefit greatly from the new features to update their code base. In this book, we will mainly refer to C17, as defined in JTC1/SC22/WG14 [2018], but at the time of this writing some compilers don’t implement this standard completely. If you want to compile the examples in this book, you will need at least a compiler that implements most of C99. For the changes that C11 added to C99, using an emulation layer such as my macro package P99 might suffice; the package is available at http://p99.gforge.inria.fr. C and C++ Programming has become a very important cultural and economic activity, and C remains an important element in the programming world. As in all human activities, progress in C is driven by many factors: corporate or individual interest, politics, beauty, logic, luck, ignorance, selfishness, ego, sectarianism (add your primary motivation here). Thus the de- velopment of C has not been and cannot be ideal. It has flaws and artifacts that can only be understood with their historical and societal context. An important part of the context in which C developed was the early appearance of its sister language, C++. One common misconception is that C++ evolved from C by adding its particular features. Although this is historically correct (C++ evolved from a very early C), it is not particularly relevant today. In fact, C and C++ separated from a common ancestor more than 30 years ago and have evolved separately ever since. But this evolution of the two languages has not taken place in isolation; they have exchanged and adopted each other’s con- cepts over the years. Some new features, such as the recent addition of atomics and threads, have been designed in close collaboration between the C and C++ standard committees. Nevertheless, many differences remain, and generally all that is said in this book is about C, not C++. Many code examples that are given will not even compile with a C++ compiler. So we should not mix sources of both languages. TAKEAWAY A C and C++ are different: don’t mix them, and don’t mix them up. Note that when you are working through this book, you will encounter many lines marked like that one. These are takeaways that summarize features, rules, recommendations, and so on. There is a list of these takeaways toward the end of the book, which you might use as a cheat sheet.
Page
14
xiii Requirements To be able to profit from this book, you need to fulfill some minimal requirements. If you are uncertain about any of these, please obtain or learn them first; otherwise, you might waste a lot of time. First, you can’t learn a programming language without practicing it, so you must have a decent programming environment at your disposal (usually on a PC or laptop), and you must master it to some extent. This environment can be integrated (an IDE) or a collection of separate utilities. Platforms vary widely in what they offer, so it is difficult to advise on specifics. On Unix-like environments such as Linux and Apple’s macOS, you will find editors such as emacs and vim, and compilers such as c99, gcc, and clang. You must be able to do the following: 1 Navigate your file system. File systems on computers are usually organized hier- archically in directories. You must be able to navigate through these to find and manipulate files. 2 Edit programming text. This is different from editing a letter in a word processing environment. Your environment, editor, or whatever it is called should have a basic understanding of the programming language C. You will see that if you open a C file (which usually has the file extension .c). It might highlight some keywords or help you indent your code according to the nestedness of {} brackets. 3 Execute a program. The programs you will see here are very basic at first and will not offer you any graphical features. They need to be launched in the command line. An example of such a program that is launched that way is the compiler. On Unix- like environments, the command line is usually called a shell and is launched in a (or the) console or terminal. 4 Compile programming text. Some environments provide a menu button or a key- board shortcut for compilation. An alternative to that is to launch the compiler in the command line of a terminal. This compiler must adhere to recent standards; don’t waste your time with a compiler that does not conform. If you have never programmed before, this book will be tough. Knowing some of the following will help: Basic, C (historical versions), C++, Fortran, R, bash, JavaScript, Java, MATLAB, Perl, Python, Scilab, and so on. But perhaps you have had some other program- ming experience, maybe even without noticing. Many technical specifications actually come in some sort of specialized language that can be helpful as an analogy: for example, HTML for web pages and LaTeX for document formatting. You should have an idea of the following concepts, although their precise meanings may be a bit different in C than in the context where you learned them: 1 Variables — Named entities that hold values 2 Conditionals — Doing something (or not) subject to a precise condition 3 Iteration — Doing something repeatedly for a specified number of times or until a certain condition is met
Page
15
xiv ABOUT THIS BOOK Source code Many of the programming code snippets that are presented in this book are available for download as a .zip archive from the book’s website at https://gforge.inria.fr/frs/download.php/latestzip/5297/code-latest.zip This allows you to view them in context and to compile them and try them out. The archive also contains a Makefile with a description of the components that are needed to compile these files. It is centered around Linux or, more generally, POSIX systems, but it may also help you to find out what you need when you are on a different system. Exercises and challenges Throughout this book, you’ll see exercises that are meant to get you thinking about the con- cepts being discussed. These are probably best done directly along with your reading. Then there is another category called “challenges.” These are generally more demanding. You will need to do some research to even understand what they are about, and the solutions will not come all by themselves: they will require effort. They will take more time, sometimes hours or, depending on your degree of satisfaction with your work, even days. The subjects covered in these challenges are the fruit of my own personal bias toward “interesting questions” from my personal experience. If you have other problems or projects in your studies or your work that cover the same ground, they should do equally well. The important aspect is to train yourself by first searching for help and ideas elsewhere, and then to get your hands dirty and get things done. You will only learn to swim if you jump into the water. Organization This book is organized in levels, numbered from 0 to 3. The starting level 0, named "En- counter," will summarize the very basics of programming with C. Its principal role is to remind you of the main concepts we have mentioned and familiarize you with the special vocabulary and viewpoints that C applies.1 By the end of it, even if you don’t have much experience in programming with C, you should be able to understand the structure of simple C programs and start writing your own. The "Acquaintance" level 1 details most principal concepts and features such as control structures, data types, operators, and functions. It should give you a deeper understanding of the things that are going on when you run your programs. This knowledge should be sufficient for an introductory course in algorithms and other work at that level, with the notable caveat that pointers are not yet fully introduced. The "Cognition" level 2 goes to the heart of the C language. It fully explains pointers, familiarizes you with C’s memory model, and allows you to understand most of C’s library interface. Completing this level should enable you to write C code professionally; it there- fore begins with an essential discussion about the writing and organization of C programs. I personally would expect anybody who graduated from an engineering school with a major 1 One of C’s special viewpoints is that indexing starts at 0, and not at 1 as in Fortran.
Page
16
xv related to computer science or programming in C to master this level. Don’t be satisfied with less. The "Experience" level 3 then goes into detail about specific topics, such as performance, reentrancy, atomicity, threads, and type-generic programming. These are probably best dis- covered as you go, which is when you encounter them in the real world. Nevertheless, as a whole, they are necessary to round off the discussion and to provide you with full expertise in C. Anybody with some years of professional programming in C or who heads a software project that uses C as its main programming language should master this level. About the author Jens Gustedt completed his studies of mathematics at the University of Bonn and Berlin Technical University. His research at that time covered the intersection between discrete mathematics and efficient computation. Since 1998, he has been working as a senior scientist at the French National Institute for Computer Science and Control (INRIA), first in the LORIA lab, Nancy, and since 2013 in the ICube lab, Strasbourg. Throughout his career, most of his scientific research has been ac- companied by the development of software, at the beginning mostly in C++, and then later exclusively in C. He now serves AFNOR as an expert on the ISO committee JTC1/SC22/WG14 and is co-editor of the C standard document ISO/IEC 9899:2018. He also has a successful blog that deals with programming in C and related topics: https://gustedt.wordpress.com.
Page
17
About the cover illustration The figure on the cover of Modern C is captioned “Femme Dalmate” or woman from Dal- matia. The illustration is taken from a collection of dress costumes from various countries by Jacques Grasset-St-Sauveur (1757-1810), titled Costumes de Différents Pays, published in France in 1788. Each illustration is finely drawn and colored by hand. The rich variety of Grasset-St-Sauveur’s collection reminds us vividly of how culturally apart the world’s towns and regions were just 200 years ago. Isolated from each other, people spoke different dialects and languages. In the streets or in the countryside, it was easy to identify where they lived and what their trade or station in life was just by their dress. The way we dress has changed since then and the diversity by region, so rich at the time, has faded away. It is now hard to tell apart the inhabitants of different continents, let alone different towns, regions, or countries. Perhaps we have traded cultural diversity for a more varied personal life—certainly for a more varied and fast-paced technological life. At a time when it is hard to tell one computer book from another, Manning celebrates the inventiveness and initiative of the computer business with book covers based on the rich diversity of regional life of two centuries ago, brought back to life by Grasset-St-Sauveur’s pictures. xvi
Page
18
Level 0 Encounter Our mascot for this level is the magpie, one of the most intelligent nonhuman species on earth. They are capable of elaborate social rituals and usage of tools. This first level of the book may be your first encounter with the programming language C. It provides you with a rough knowledge about C programs, their purpose, their structure, and how to use them. It is not meant to give you a complete overview, it can’t and it doesn’t even try. On the contrary, it is supposed to give you a general idea of what this is all about, open up questions, and promote ideas and concepts. These then will be explained in detail in the higher levels.
Page
19
(This page has no text content)
Page
20
1Getting started This chapter covers Introduction to imperative programming Compiling and running code In this chapter, I will introduce you to one simple program that has been chosen because it contains many of the constructs of the C language. If you already have programming experi- ence, you may find that parts of it feel like needless repetition. If you lack such experience, you might feel overwhelmed by the stream of new terms and concepts. In either case, be patient. For those of you with programming experience, it’s very possi- ble that there are subtle details you’re not aware of, or assumptions you have made about the language that are not valid, even if you have programmed C before. For those approaching programming for the first time, be assured that after approximately 10 pages your understand- ing will have increased a lot, and you should have a much clearer idea of what programming represents. An important bit of wisdom for programming in general, and for this book in particular, is summarized in the following citation from the Hitchhiker’s Guide to the Galaxy by Douglas Adams [1986]: TAKEAWAY B Don’t panic. It’s not worth it. There are many cross references, links, and bits of side information in the text, and there is an index at the end. Follow those if you have a question. Or just take a break. Programming in C is about having the computer complete some specific tasks. A C pro- gram does that by giving orders, much as we would express such orders in the imperative tense in many human languages; thus the term imperative programming for this particular way of organizing computer programs. To get started and see what we are talking about, consider our first program in listing 1.1: 3