5.1. The C Programming Language#

The C programming language is a high level statically typed procedural compiled programming language which most operating systems are written in because it allows the programmer the full control needed to interact with devices and hardware. You have probably already learned the language in a previous course, but this course will utilize some of its advanced features that have probably not been taught in those introductory courses. We don’t expect you to memorize the advanced features of he language; instead you should reference this searchable documentation as you need to, or if you prefer the famous K&R book that can be downloaded for free. Make sure you have at least a basic understanding of:

  • Functions: declarations and definitions

  • Variables: definitions, usage

  • Data types and conversion between them

  • What operators are available

  • Control flow (if statements, loops)

  • Arrays and strings, array-to-pointer decay

  • Pointers and pointer arithmetic

  • Memory management (malloc, free, etc.)

  • Structs and unions

  • Pre-processor directives

One thing that you should be aware of is that the C programming language, by giving absolute control to the programmer, makes it really easy to shoot yourself in the foot. We strongly recommend using a set of tools and techniques that will give you some degree of foot armor:

  • Use some form of coding style, e.g., this website contains the preferred coding style for the Linux kernel. Adhering to a style will increase productivity so you and whoever else looks at your code will spend less time trying to understand what you wrote.

  • As described here always compile your programs with -Wall and -Werror to enable the compiler to catch many bugs.

  • Use debuggers rather than print to debug your program.

  • Use tools like valgrind, or sanitizer arguments to add extra runtime checks to detect undefined behavior or memory leaks.

Most of all, write extensive unit and integration tests (see this chapter) as you develop your code. You will be shocked how many times you will avoid debugging the same problem repeatedly by doing this.