What this book covers
This book has 7 parts. In each of these 7 parts, we cover some particular aspects of C programming. The first part focuses upon how to build a C project, the second part focuses on memory, the third on object orientation, and the fourth primarily looks at Unix and its relationship to C. The fifth part then discusses concurrency, the sixth covers inter-process communication, and finally the seventh part of the book is about testing and maintenance. Below is a summary of each of the 23 chapters found in this book.
Chapter 1, Essential Features: This chapter is about the essential features found in C that have a profound effect on the way we use C. We will be using these features often throughout the book. The main topics are preprocessing and directives to define macros, variable and function pointers, function call mechanisms, and structures.
Chapter 2, Compilation and Linking: As part of this chapter, we discuss how to build a C project. The compilation pipeline is studied in great detail, both in terms of the pipeline as a whole and in terms of the individual pipeline components.
Chapter 3, Object Files: This chapter looks at the products of a C project after having built it using the compilation pipeline. We introduce object files and their various types. We also take a look inside these object files and see what information can be extracted.
Chapter 4, Process Memory Structure: In this chapter, we explore a process's memory layout. We see what segments can be found in this memory layout and what static and dynamic memory layouts mean.
Chapter 5, Stack and Heap: As part of this chapter, we discuss the Stack and Heap segments specifically. We talk about the Stack and Heap variables and how their lifetime is managed in C. We discuss some best practice regarding Heap variables and the way that they should be managed.
Chapter 6, OOP and Encapsulation: This is the first chapter in a group of four chapters discussing object orientation in C. As part of this chapter, we go through the theory behind object orientation and we give important definitions to the terms often used in the literature.
Chapter 7, Composition and Aggregation: This chapter focuses upon composition and a special form of it: aggregation. We discuss the differences between composition and aggregation and give examples to demonstrate these differences.
Chapter 8, Inheritance and Polymorphism: Inheritance is one of the most important topics in object-oriented programming (OOP). In this chapter, we show how an inheritance relationship can be established between two classes and how it can be done in C. Polymorphism is another big topic that is discussed as part of this chapter.
Chapter 9, Abstraction and OOP in C++: As the final chapter in the third part of the book, we talk about abstraction. We discuss abstract data types and how they can be implemented in C. We discuss the internals of C++ and we demonstrate how object-oriented concepts are implemented in C++.
Chapter 10, Unix – History and Architecture: You cannot talk about C and forget about Unix. In this chapter, we describe why they are strongly bound to each other, and how Unix and C have helped one another to survive thus far. The architecture of Unix is also studied, and we see how a program uses the functionalities exposed by the operating system.
Chapter 11, System Calls and Kernel: In this chapter, we focus on the kernel ring in the Unix architecture. We discuss system calls in greater detail and we add a new system call to Linux. We also talk about various types of kernels, and we write a new simple kernel module for Linux to demonstrate how kernel modules work.
Chapter 12, The Most Recent C: As part of this chapter, we take a look at the most recent version of C standard, C18. We see how it is different from the previous version, C11. We also demonstrate some of the newly added features in comparison to C99.
Chapter 13, Concurrency: This is the first chapter of the fifth part of the book, and it is regarding concurrency. This chapter mainly talks about concurrent environments and their various properties such as interleavings. We explain why these systems are non-determinant and how this property can lead to concurrency issues such as race conditions.
Chapter 14, Synchronization: In this chapter, we continue our discussion regarding concurrent environments, and we discuss the various types of issues that we can expect to observe in a concurrent system. Race conditions, data races, and deadlocks are among the issues that we discuss. We also talk about the techniques that we can utilize to overcome these issues. Semaphores, mutexes, and condition variables are discussed in this chapter.
Chapter 15, Thread Execution: As part of this chapter, we demonstrate how a number of threads can be executed and how they can be managed. We also give real C examples about the concurrency issues discussed in the previous chapter.
Chapter 16, Thread Synchronization: In this chapter, we look at the techniques that we can use to synchronize a number of threads. Semaphores, mutexes, and condition variables are among the notable topics that are discussed and demonstrated in this chapter.
Chapter 17, Process Execution: This chapter talks about the ways that we can create or spawn a new process. We also discuss push-based and pull-based techniques for sharing state among a number of processes. We also demonstrate the concurrency issues discussed in Chapter 14, Synchronization using real C examples.
Chapter 18, Process Synchronization: This chapter mainly deals with available mechanisms to synchronize a number of processes residing on the same machine. Process-shared semaphores, process-shared mutexes, and process-shared condition variables are among the techniques discussed in this chapter.
Chapter 19, Single-Host IPC and Sockets: In this chapter, we mainly discuss push-based interprocess communication (IPC) techniques. Our focus is on the techniques available to processes residing on the same machine. We also introduce socket programming, and the required background to establish channels between processes residing on different nodes in a network.
Chapter 20, Socket Programming: As part of this chapter, we discuss socket programming through code examples. We drive our discussion by bringing up an example that is going to support various types of sockets. Unix domain sockets, TCP, and UDP sockets operating on either a stream or a datagram channel are discussed.
Chapter 21, Integration with Other Languages: In this chapter, we demonstrate how a C library, built as a shared object file, can be loaded and used in programs written with C++, Java, Python, and Golang.
Chapter 22, Unit Testing and Debugging: This chapter is dedicated to testing and debugging. For the testing half, we explain various levels of testing, but we focus on unit testing in C. We also introduce CMocka and Google Test as two available libraries to write test suites in C. For the debugging half, we go through various available tools that can be used for debugging different types of bugs.
Chapter 23, Build Systems: In the final chapter of the book, we discuss build systems and build script generators. Make, Ninja, and Bazel are the build systems that we explain as part of this chapter. CMake is also the sole build script generator that we discuss in this chapter.