Video Coming Soon...

Created by Zed A. Shaw Updated 2024-12-10 18:57:40

This Book Is Not Really about C

Please don't feel cheated, but this book is not about teaching you C programming. You'll learn to write programs in C, but the most important lesson you'll get from this book is rigorous defensive programming. Today, too many programmers simply assume that what they write works, but one day it will fail catastrophically. This is especially true if you're the kind of person who has learned mostly modern languages that solve many problems for you. By reading this book and following my exercises, you'll learn how to create software that defends itself from malicious activity and defects.

I'm using C for a very specific reason: C is broken. It is full of design choices that made sense in the 1970s but make zero sense now. Everything from its unrestricted wild use of pointers to its severely broken NUL terminated strings are to blame for nearly all of the security defects that hit C. It's my belief that C is so broken that it's the most difficult language to write securely in wide use today. I would fathom that Assembly Language is actually easier to write securely than C. To be honest, and you'll find out that I'm very honest, I don't think that anybody should be writing new C code.

If that's the case, then why am I teaching you C? Because I want you to become a better, stronger programmer, and there are two reasons why C is an excellent language to learn if you want to get better. First, C's lack of nearly every modern safety feature means you have to be more vigilant and more aware of what's going on. If you can write secure, solid C code, you can write secure, solid code in any programming language. The techniques you learn will translate to every language you use form now on. Secondly, learning C gives you direct access to a mountain of legacy code, and teaches you the base syntax of a large number of descendant languages. Once you learn C, you can more easily learn C++, Java, Objective-C, and JavaScript, and even other languages become easier to learn.

I don't want to scare you away by telling you this, because I plan to make this book incredibly fun, easy, and devious. I'll make it fun to learn C by giving you projects that you might not have done in other programming languages. I'll make this book easy by using my proven pattern of exercises that has you doing C programming and building your skills slowly. I'll make it devious by teaching you how to break and then secure your code so you understand why these issues matter. You'll learn how to cause stack overflows, illegal memory access, and other common flaws that plague C programs so that you know what you're up against.

Getting through this book will be challenging, like all of my books, but when you're done you will be a far better and more confident programmer.

The Undefined Behaviorists

By the time you're done with this book, you'll be able to debug, read, and fix almost any C program you run into, and then write new, solid C code should you need to. However, I'm not really going to teach you official C. You'll learn the language, and you'll learn how to use it well, but official C isn't very secure. The vast majority of C programmers out there simply don't write solid code, and it's because of something called Undefined Behavior (UB). Undefined Behavior is a part of the American National Standards Institute C standard that lists all of the ways that a C compiler can disregard what you've written. There's actually a part of the standard that says if you write code like this, then all bets are off and the compiler doesn't have to do anything consistent. For a bit of background, C defines strings as blocks of memory that end in a NUL byte, or a 0 byte (to simplify the definition). Since many strings come from outside the program, it's common for a C program to receive a string without this NUL byte. When it does, the C program attempts to read past the end of this string and into the memory of the computer, causing your program to crash. Every other language developed after C attempts to prevent this, but not C. C does so little to prevent UB that every C programmer seems to think it means they don't have to deal with it. They write code full of potential NUL byte overruns, and when you point them out to these programmers, they say, "Well that's UB, and I don't have to prevent it." This reliance on C's large number of undefined behaviors is why most C code is so horribly insecure.

I write C code to try to avoid UB by either writing code that doesn't trigger it, or writing code that attempts to prevent it. This turns out to be an impossible task because there is so much UB that it becomes a Gordian knot of interconnected pitfalls in your C code. As you go through this book, I'll point out ways you can trigger UB, how to avoid it if you can, and how to trigger it in other people's code if possible. However, you should keep in mind that avoiding the nearly random nature of UB is almost impossible, and you'll just have to do your best.

WARNING: You'll find that hardcore C fans frequently will try to beat you up about UB. There's a class of C programmers who don't write very much C code but have memorized all of the UB just so they could beat up a beginner intellectually. If you run into one of these abusive programmers, please ignore them. often, they aren't practicing C programmers, they are arrogant, abusive, and will only end up asking you endless questions in an attempt to prove their superiority rather than helping you with your code. Should you ever need help with your C code, simply email me at help@learncodethehardway.org, and I will gladly help you.

C Is a Pretty and Ugly Language

The presence of UB though is one more reason why learning C is a good move if you want to be a better programmer. If you can write good, solid C code in the way I teach you, then you can survive any language. On the positive side, C is a really elegant language in many ways. Its syntax is actually incredibly small given the power it has. There's a reason why so many other languages have copied its syntax over the last 45 or so years. C also gives you quite a lot using very little technology. When you're done learning C, you'll have an appreciation for something that is very elegant and beautiful but also a little ugly at the same time. C is old, so like a beautiful monument, it will look fantastic from about 20 feet away, but when you step up close, you'll see all the cracks and flaws it has.

Because of this, I'm going to teach you the most recent version of C that I can make work with recent compilers. It'll be a practical, straightforward, simple, yet complete subset of C that works well, works everywhere, and avoids many pitfalls. This is the C that I use to get real work done, and not the encyclopedic version of C that hardcore fans try and fail to use.

I know the C that I use is solid because I spent two decades writing clean, solid C code that powered large operations without much failure at all. My C code has probably processed trillions of transactions because it powered the operations of companies like Twitter and AirBNB. It rarely failed or had security attacks against it. In the many years that my code powered the Ruby on Rails Web world, it's run beautifully and even prevented security attacks, while other Web servers fell repeatedly to the simplest of attacks.

My style of writing C code is solid, but more importantly, my mindset when writing C is one every programmer should have. I approach C, and any programming, with the idea of preventing errors as best I can and assuming that nothing will work right. Other programmers, even supposedly good C programmers, tend to write code and assume everything will work, but rely on UB or the operating system to save them, neither of which will work as a solution. Just remember that if people try to tell you that the code I teach in this book isn't "real C." If they don't have the same track record as me, maybe you can use what I teach you to show them why their code isn't very secure.

Does that mean my code is perfect? No, not at all. This is C code. Writing perfect C code is impossible, and in fact, writing perfect code in any language is impossible. That's half the fun and frustration of programming. I could take someone else's code and tear it apart, and someone could take my code and tear it apart. All code is flawed, but the difference is I try to assume my code is always flawed and then prevent the flaws. My gift to you, should you complete this book, is to teach you the defensive programming mindset that has served me well for two decades, and helped me make high-quality, robust software.

What You Will Learn

The purpose of this book is to get you strong enough in C that you'll be able to write your own software with it or modify someone else's C code. After this book, you should read The C Programming Language (Prentice Hall 1988) a book by the creators of the C language, also called K&R C. What I'll teach you is

By the final exercise, you will have more than enough ammunition to tackle basic systems software, libraries, and other smaller projects.

How to Read This Book

This book is intended for programmers who have learned at least one other programming language. I refer you to my book Learn Python the Hard Way, 5th Edition if you haven't learned a programming language yet. It's meant for beginners and works very well as a first book on programming. Once you've completed Learn Python the Hard Way, then you can come back and start this book.

For those who've already learned to code, this book may seem strange at first. It's not like other books where you read paragraph after paragraph of prose and then type in a bit of code here and there. Instead, there are videos of lectures for each exercise, you code right away, and then I explain what you just did. This works better because it's easier to explain something you've already done than to speak in an abstract sense about something you aren't familiar with at all.

Because of this structure, there are a few rules that you must follow in this book:

If you follow these rules, do everything in the book, and still can't code C, then you at least tried. It's not for everyone, but just trying will make you a better programmer.

The Videos

Included in this course are videos for every exercise, and in many cases, more than one video for an exercise. These videos should be considered essential to get the full impact of the book's educational method. The reason for this is that many of the problems with writing C code are interactive issues with failure, debugging, and commands. C requires much more interaction to get the code running and fix problems, unlike languages like Python and Ruby where code just runs. It's also much easier to show you a video lecture on a topic, such as pointers or memory management, where I can demonstrate how the machine is actually working.

I recommend that as you go through the course, you plan to watch the videos first, and then do the exercises unless directed to do otherwise. In some of the exercises, I use one video to present a problem, and then another to demonstrate the solution. In most of the other exercises, I use a video to present a lecture, then you do the exercise and complete it to learn the topic.

The Core Competencies

I'm going to guess that you have experience using a lesser language. One of those usable languages that lets you get away with sloppy thinking and half-baked hackery like Python or Ruby. Or, maybe you use a language like Lisp that pretends the computer is some purely functional fantasy land with padded walls for little babies. Maybe you've learned Prolog, and you think the entire world should just be a database where you walk around in it looking for clues. Even worse, I'm betting you've been using an integrated development environment (IDE), so your brain is riddled with memory holes, and you can't even type an entire function's name without hitting CTRL-SPACE after every three characters.

No matter what your background is, you could probably use some improvement in these four areas:

Learning C makes you a better programmer because you are forced to deal with these issues earlier and more frequently. You can't be sloppy about what you write or nothing will work. The advantage of C is that it's a simple language that you can figure out on your own, which makes it a great language for learning about the machine and getting stronger in these core programming skills.

Previous Lesson Next Lesson

Register for Learn C the Hard Way

Register today for the course and get the all currently available videos and lessons, plus all future modules for no extra charge.