C

These are my notes on (re-)learning C. There may be mistakes or things I've not explained clearly, or I've not covered every single edge case. Please don't barge in and tell me what I've done wrong, or that you disagree with an opinion - that spoils the learning experience (if I want / need help, I will ask for it).

Pros and cons

Despite a lot of bad press, C is still heavily used, although a lot of new projects will be written in Go or Rust. If you want to write a kernel or a game engine though, you're probably going to reach for C for the time being (Rust has been introduced to the Linux kernel, but it is a tiny part, and doing so means that a Rust compiler is now required for some parts of the kernel).

Portability: C is probably the most portable language in existence (or perhaps more precisely, the language with the highest portability potential - you still have to think about things like file paths). Chances are if you need to work with a piece of hardware, there is a C compiler out there which can produce executable code for it. This is not the case for Go or Rust, although their architecture support is improving over time, and particularly with LLVM for Rust.

Size: C is a very small and simple language. Even if you consider the standard library to be part of the language, it's possible for a sole developer to understand all of it, which isn't the case for PHP, Go or Rust.

Manual memory management: This is probably the biggest disadvantage of C. Not only does manual memory management add boilerplate and cognitive load, it has been the source of many bugs over the years - some of which become security issues because if you can corrupt memory, you can often use that as a stepping stone to do bad things.

Pointers: Partly tied to manual memory management, pointers are one of the hardest things to get your head round in C. Pointer arithmetic in particular is largely a C thing, and therefore you can't bring the concept over from another language.

Arrays: Arrays are similar to, but not the same as, pointers. This causes a lot of confusion, especially as sometimes you can treat a pointer as an array (e.g. if you allocate memory for 10 itnegers on the heap, you can usually access each integer using the array syntax).

Backwards compatibility: Code written decades ago will still, in most cases, work with the latest compilers. It is unusual for a new C standard to break existing code.

Standards

C is still being updated, albeit not as quickly as languages such as Rust and Go. You can see this as an advantage or disadvantage.

C89: The first proper standard, targeting this gives you the widest portability.

C99: Some much needed improvements to C89, such as single line comments (//), variable declaration anywhere within a function (C89 requires declarations at the top, though assignment is possible anywhere) and fixed-width integer types (e.g. if you declare int32_t you are guaranteed to get a 32 bit integer). Most projects seem to use this as a minimum now.

Unfortunately C standards are controlled by the International Standards Organisation, which keeps the final version of standards behind a paywall, and therefore C is not a truly open language. It's also difficult to contribute to the standards unless you happen to work for a large organisation which is willing to give you paid time off to work on this (there are exceptions of course).

Hello World

Hello World is straightforward in C