PREFACE
Another day, another essay. For the “Marvel-Of-Software-Engineering series”, I focus a lot on hardware and web applications, but I typically don’t go into a deep dive about their codebases or the specific programming languages that they implement. So this essay might be different, considering how I’m diving into a specific programming language.
I spent some time debating about whether a Programming Language is relevant as a “Marvel-Of-Software-Engineering”. On a technical scale, Programming Languages (architecture) can be extremely complex and impressive underneath all the abstractions, especially when it comes to optimization/speed. The language that I’m going to be yapping about is amongst the fastest and most influential out there.
Also, yeah, summer break is reaching its end. This is going to be the last Marvel-Of-Software-Engineering I’ll do for quite a while. Although I do plan on posting one last essay in the Chatting Area for this Summer, it is very likely going to be about a very specific person in Theoretical Computer Science. Alright, let’s get this over with.
AN ESSAY ABOUT C
Linus Torvalds’s Linux, Microsoft Windows, Google Android, Apple iOS. These are the most used Operating Systems and Kernels in the world. We use these systems to access and manage our computing devices at hardware and software level. They are amongst the most vital technologies that we use to interact across the entire internet. Typically, with cases like this, one would expect a lot of competition. But all these operating systems also utilize one thing in common, that is they were written in the programming language known as C.
How we write computer programs has changed a lot over the years. The first software to be stored on a physical computer was created in 1948. Tom Kilburn wrote it (on a computer known as the Manchester Baby) to find the largest possible factor of 262,144. There were no programming languages then. The codebase for that software was entirely written in thousands of raw 1s and 0s, AKA Binary/Machine Code. Computers couldn’t understand English characters from the get-go, but they were capable of understanding a bunch of bits. The mainstream practice of writing Machine Code by hand would stay that way for quite a while.
By the 1950s, the era of typing 1s and 0s was over. Many codebases were now written in a language called Assembly (which had English characters). Now, Assembly had a very fast runtime, which made it highly attractive to programmers. It did have flaws though, one of the more egregious ones was about portability. Different computers have different architectures, and an Assembly codebase written for a specific chip might break when copied into another chip. This resulted in many programmers having to tediously rewrite thousands of lines of Assembly into different architectures. Also, if we’re going to compare Assembly with modern languages, Assembly is definitely considered extremely unreadable even to the likes of C++.
(Ken Thompson and Dennis Ritchie)
The reliance on Assembly would end in the 1970s. During that period, there were 2 Computer Scientists at the legendary Bell Labs: Ken Thompson and Dennis Ritchie. They were working on building a new operating system called Unix. Unix was initially written in Assembly, but the 2 scientists quickly ran into the portability issue that Assembly was infamous for having. To handle this portability issue, they developed a new language called B, but that had its own limitations (e.g., no distinct data types like booleans). To combat the limitations of B, Dennis Ritchie and Ken Thompson would create the language C in 1972.
Unix was then rewritten in C and it would become one of the most influential software of all time. Later in the 1980s, C would increase in popularity. Famous for its speed, readability, and portability, it replaced Assembly and became one of the most popular languages of all time. Now, regarding the speed specifically, there are a variety of intentional decisions that made C as fast as it is.
See, for many programming languages used today (e.g., Python, Java, Golang), they have something called a Garbage Collection. If you want to smoothly run a massive program in any type of language, you need RAM. The computer will use the RAM to store your program’s data (e.g., variables). The computer’s CPU will then read all that data stored in the RAM extremely quickly and return an output at high speed. As far as what the Garbage Collection does, it reads through the program. When it discovers any particular data that has no further use, that obsolete data is disposed of so it doesn’t take up valuable space in the computer’s memory.
But C is different, it doesn’t have a built-in garbage collection. Instead of having the computer deal with allocating all the memory, it has the developer manually allocate the memory themselves. When a piece of data is found with no further use in the program, the developer will have to manually write lines of code that deletes the data from memory. C also gives the programmer no safety nets when it comes to this sort of thing. On the plus side, Garbage Collectors typically involve pausing the program to scan through the entire codebase, which can slow down runtime and performance. So C compensates further memory-allocation work from the programmer with a better runtime. Also, letting a programmer decide the specifics behind allocating RAM storage goes a long way in operating systems development.
Now this leads us to one of the larger points of this post, the intentional design behind C is naturally quite different in comparison to most production languages used in codebases today. One way to emphasize it is through data structures, built-in ways to store some important data in your program (think of the Arrays in the MakeCode Editor). For example, Python has a wide variety of different data structures built directly into the language itself (e.g., Hashmaps/Dictionaries). Meanwhile, C is much more limited with how many built-in data structures they give you.
(Example of a Hashmap/Dictionary written in Python, should hopefully be self-explanatory as to what it does. Anyways, C does not have a built-in hashmap data structure. If you want a hashmap in your C program, you would need to code that specific data structure yourself)
But the one thing that truly separates C from modern production languages isn’t just about the efficiency, it’s the close look at the hardware level that C gives you. Let me remind you once again about C having no garbage collection and programmers have to manually allocate computer memory. The programmers are explicitly controlling the computer’s hardware and warping it to their liking, working with bytes and all of that. It’s difficult trying to find such an opportunity in other production languages out there, although others do exist.
Now, even after over 80 years and we have readable programming languages written through english characters, the computer is still incapable of understanding surface-level English. They can only understand binary and bits. To handle this, when you run your code, many production languages (e.g., Java) will run an interpreter/compiler that converts every last line of code into binary code, so the computer can actually understand what your code is supposed to do.
Now C utilizes this same compiler logic, but with some additional nuance. Before running your program, C will be compiled into binary code. This shaves off valuable time that would have been taken up by the translation process as soon as you run the program. This further proves the point of C being faster than most programming languages today.
(This is an Abstract Syntax Tree. Every line of code is first broken down into tokens and then converted into that data structure by the compiler. In a nutshell, the compiler will then utilize special algorithms to traverse through that AST for grammar checking and then generate Machine Code out of the nodes. Honestly, the entire process of how the compiler does its job deserves its standalone essay)
But as usual, when C gives you an opportunity for less delay/latency, you can always expect more work needing to be done as a programmer. One could expect having to write a lot of additional files and scripts that dictate the specific way the compilation process is meant to go. Granted, compilers/interpreters are actually very complicated under the hood, so extra configuration work looks a lot more pleasant in comparison.
You’ll find that there are several other languages that include a large capital “C” in their name. Perhaps the most popular language that has that similar prefix is C++. Bjarne Stroustrup also started the language in Bell Labs. Years back when Bjarne was conducting his PhD at the University of Cambridge, he was using a language called Simula. That language was very useful and contained many features (e.g., Classes, Object-Oriented Programming) beneficial for designing systems. However, Bjarne also found Simula to be a bit too slow for his liking when it came to executing massive systems.
Bjarne also used C, it was much faster when it came to executing massive features and closer to the hardware level. However, as mentioned previously, C’s design was very minimalistic and it lacked several features that Simula had (e.g., Classes). This made it a much larger hassle to design and program complex systems and software. Bjarne began wanting to have a language that combined the exceptional performance of C and all the high-level features of Simula. Bjarne, who was now at Bell Labs, in 1979 began developing a new language called “C with Classes.” That language would be renamed to C++ and then released in 1985.
(Bjarne Stroustrup)
As everything implies, C++ is an extension of C. It kept the most redeeming features behind C (e.g., manual memory allocation) and added even more high-level features built into the language (e.g., Classes). One would assume that C++ would replace C completely, but it didn’t. A lot has to do with simplicity. C++ is known for having a very dense and complicated syntax, meanwhile C is much easier on the eyes. Programmers can have an easier time debugging errors in C compared to C++. C++ also has a lot of abstraction due to the several high-level features that it has, so C is a lot closer to the hardware level and the programmer is given a lot more autonomy/freedom in that case. One of the greatest programmers of all time, John Carmack said this, which sums up the entire argument regarding C and C++:
(…)
C is a very simple and readable language. C is a very portable language. C is a very fast language. Operating systems and kernels pretty much use C for all these exact reasons. C is also used in codebases outside of Operating Systems or Kernels. High-Frequency Trading firms use C (combined with C++) due to the ultra-low latency it comes with. Companies (e.g., NVIDIA) use C to power their hardware products and embedded systems. As I mentioned at the start, the way we write computer programs has been continuously evolving as time went on. With how much C is in codebases today though, it might be a very long time before it gets fully replaced.






