Why is the C Programming Language the Language of Freedom?
In this article I will explain why I think the C programming language is one of the best programming language for maintaining developer independence and protecting intellectual property. C is a relatively simple language to learn the basics of but it is a language that can take decades of practice to truly master. It was invented in 1972 by the late great Dennis Ritchie. According to an article referenced in the Wiki entry for C its popularity has declined a bit for application software even though it is still extremely popular. What isn’t so obvious is that at one time (between the middle 1980s to late 1990s) C was the dominant programming language when the number of programming languages available to the average software developer were much, much less common than they are today. There was simply more of the pie to go around to languages that existed then.
Also the availability of high level scripting languages for application software were almost non-existent. Today the situation is much different. There are many “casual software developers” who never went through formal computer science training and therefore never really would consider the complexity of writing large pieces of application software in C. Also, with the vast number of modern competitors it seems like C might be something of an old guy trying to keep up with the young crowd. However this is quite misleading.
C is about as close as one can program to the hardware in a relatively high level language. Below C there is Assembly and below that there is Machine code. C stands as the foundation for all modern operating system cores and most other programming languages! The modern darling Python is written in the C programming language! It is no surprise that Python is one of the more popular scripting language. C is as fast as you can get in a programming language above assembly. There have been many marketing gimmicks that speak about the speed of .NET speeding up due to post run optimizations, etc. and the power of modern computers making ease of programming more important than efficiency. While there is always a shred of truth to marketing we should not loose sight of the fundamentals.
We must also address the frequently misunderstood relationship between C and C++. C++ is built on C and for those in the know it actually is base C combined with a lot of extra layers and overhead added to provide for object oriented code development etc. In some cases the C++ pre-processor actually converts C++ code to C type code before executing the final step compilation to get the machine specific binary. This parasitic relationship of C++ to C has created much confusion over the years for people wanting to learn C but getting caught up in the glamour of C++ as both compilers are usually bundled together and operate seamlessly in the same Integrated Development Environment (IDE). C++ is a monster compared to C. Individuals have written C compilers, it usually takes large corporations to write C++ compilers. The difference in overhead between the languages is astounding.
I consider C++ to be a beautiful language and I code in it myself. However it is not C. It is C like syntax that uses C to build the complex framework necessary to make a language like C++ possible. In exchange for the orders of a magnitude more complexity under the hood with C++ you seem to get the best of both worlds, a language that is blazing fast compared to many other high level languages of its type but a language with many “modern” programming features such as object oriented capability and a plethora of libraries that seem to be able to handle any task you can imagine. The price you pay however it you give up your tool development to a select few with the huge resources necessary to build C++ compilers and maintain the insane levels of documentation needed for the C++ libraries. Also while the performance is good compared to its peers, sometimes the best of the lot, C++ is nowhere close to the performance of pure C.
For certain tasks it is alright to write in a programming language that is orders of a magnitude slower than C but when you need (or want) the maximum potential out of your hardware you look no where else than C. There are many languages that have their compilers and interpreters programmed in C such as the previously mentioned Python and benefit from C’s raw speed and power due to this. Some high level languages that use C to build their compilers tout the speed of their compiled binaries as being “nearly equal to C” but in reality this is due to the tests conducted. Building large pieces of software in C is like building the great Pyramids, one stone at a time. Bit by bit the layers of code come together to form a monolithic piece of software that runs almost as fast as a whole as when you started building the smallest parts months or years previous. This is due to the way the C compiler compiles the finished binary files down to machine code. Due to the fact that the language is so close to how a computer operates, the layers and layers of code that you write get packed down into something that the computer runs at lightening speed no matter the complexity of the software from the number of lines of code standpoint.
Now it is possibly to write terrible C code that is woefully inefficient by C standards. These are standards where you can get as efficient as humanly possible, but unless you are actually trying to write the slowest code possible it is almost impossible to write C code that is slower than code executed in higher level languages. When written well, C with just modest care paid to efficiency yields code that is impossible to best in performance and efficiency in higher level languages!
If we put the efficiency and speed of a C compiler aside and consider the complexity of building it we see that due to its limited subset of default libraries (compared to C++ and almost every other higher level language) the C compiler is a relatively simple compiler to create from scratch for a new platform. At first glance this may not seem to be an issue, after all big companies create compilers for new platforms don’t they? The answer is they shouldn’t be the only ones! With C you have a language that can run on any microprocessor in existence, a compiler an individual with enough dedication can write and a compiler and language with which it has been proven one can write any type of software there is. To top it off the code you write is guaranteed to fun faster and take less resource than anything else out there (except Assembly or machine code for the platform). The price you pay is the learning curve to get good enough in C to equal the ease of application software creation in higher level languages.
C isn’t for everyone. There are many use cases where people should stay in their scripting or high level compiled languages due to the tasks at hand. If the task will take 2 seconds in a C program and 2 minutes in a scripting language but the task is done very infrequently then why spend the extra time constructing a C program? In the C program you may have to build many of the components yourself when your high level scripting language provides them all pre-built making your construction of the program 10 to 20 times easier.
Where C is important for everyone who uses a computer is in understanding the freedom it gives the “small guy” (or small gal) even if they never used or will never use a C compiler in their life. No corporation can take advantage of users when a C compiler and a healthy army of C developers exist for the platform. They can only set the rules of the Operating System (OS) and due to the speed constraints the OS itself has its core written in C! The minute developers hand control of their base tool kits over to corporations they are asking to be taken advantage of. The open source movement would be impossible without the C compiler which allowed for the creation of the open source tool chains. These tool chains were used to build higher and higher level languages ensuring freedom for everyone and escape from the corporate jail that the expensive, cumbersome and poorly documented commercial compiler offerings of decades previous brought to the table.
With the ability to write a free or even a cheap C compiler for a platform and the availability of many C developers an entire software ecosystem can spring forth, built by the people, for the people. Competition and free enterprise can flourish. The way to destroy the C language is to significantly reduce the number of C developers and the rewards they can gain from programming in the language. By flooding the market with a dizzying array of free compilers supported by big name corporate sponsors who tout the benefits of these new languages that took large teams millions of dollars to build, corporate entities can split the developer base and weaken the ecosystem. As long as users higher up in the compiler/interpreter ecosystem appreciate those toiling in the lower reaches of the machine jungle the entire system stays fair.
When you construct large programs in C you build a toolkit. You construct your own libraries of functions that you can reuse and constantly optimize for the rest of your life. The C standard is remarkably stable. You can write code today taking a little care that would compile on a compiler from the 1970s. Can your major application .NET code from today run on a Visual Basic compiler from the late 90s even with care? Not a chance. While the syntax of the languages is near identical the plethora of components, naming conventions and the myriad of underlying layers they are built upon would make that impossible. Any computer user that has had to “update their .NET runtime to the latest version” to run even simple programs from vendors may understand what I mean.
To update the .NET run time (or any other complex framework) means the vendor controls which run times are available for which operating system and this gives the corporate entity more leverage to force the user into a vicious upgrade cycle. Not so with C. Many individuals who sell their C programs commercially are using the code base they started decades ago. Their products are incredibly fast, small and free of dependencies. You don’t have to worry about having anything installed. Their web pages usually have a message like “This application will run on any version of Windows from Windows XP onward”. Their applications are usually also 10s of time smaller and run 10s of times faster than rivals. This sort of dependency requirement (pretty much none) is a dead give away you are dealing with a master C programmer behind the scenes and the software you are using is written entirely in C.
To close this article I will tackle the problem of intellectual property rights. When an individual or small company spends month or years building a product from which they hope to derive their living in sales the loss of their intellectual property can be devastating. C gets compiled down to machine code. While it is possible to debug the machine language instructions and use modern decompilers to get a rough view of the assembly language, basic C structure and flow of the underlying program from a function standpoint this is only of interest to hackers who want to bypass licensing mechanism or security professionals who want to examine code to see if it does bad things. The magic sauce of what you created is safe. The effort to reverse engineer an entire complex C program back to source to figure out the fine technique the developer used to achieve certain tasks would mean the reverse engineers would be better off building the software themselves.
I once saw a YouTube video where a guy said he was able to recover the source code for a game from a C program. I looked at the video and as expected it was because the developers shipped the game with a debug build of the software and the full symbol lookup table on the disk! This is the equivalent of saying you can open any lock, once someone leaves the key with the lock. The debug build with full symbol table lookup is there so the developer can debug their code as it is executed and see the lines in their source code. No security is worth anything if it is ignored. Shipping a product with this was pretty much exactly like shipping the source code.
Compare this state of affairs to shipping your product in a scripting or much higher level language. These finished executables are easily decompiled to source code with almost trivial ease. All that is required is downloading the right tool from the Internet and running it against the finished product. Almost no effort is needed. The result is almost the same source code the developer wrote to create the product! In some cases it is the exact source code, line for line, character for character!
My advise to those interested in trying to earn a living from their code by selling compiled versions of it on the open market is to be very careful if your business model requires proper licensing for payment or your intellectual property on the projects means anything to you. Choose your programming language carefully. Most independent commercial software developers use free software tools when they can to reduce costs but these developers provided these tools with the aim of them being free. I have personally seen talented developers loose their shirts making the mistake of believing causal security of their products is good enough in a paid, proprietary model.
One of the reasons Linux grew so rapidly was in the early days of computing (1970s) vendors had a habit of shipping their tools with the C source code forcing the user to compile and recompile the software to their environments. This was done primarily because compiling could take many minutes to an hour and computing time was very expensive back then! Big corporations thought it better to offload the work to the consumer! The system was not unlike some open source projects do today except these were paid products. The idea of the user having their own personal computer capable of running these caliber of programs was far fetched back then. When the Linux kernel (which was a Unix kernel freely available on the PC platform) came into being two decades later many people had these millions of lines of code available to them (saved on tape, disks, etc from the 1970s) in C and got busy recompiling them. Almost overnight a free version of Unix became available for all with all of these tools that used to costs 10s of thousands of dollars on machines that cost the same. This is one of the rare cases where the small guy won due to corporate greed.
So as an enlightened software developer or computer user of the second decade of the 21st century one should always be wary of giving away control of the very tools one needs to create. Giving away control to people who wish to exploit you for as much money as they can get out of you is a recipe for disaster. Understanding the vital importance of the C compiler and ecosystem to the small guy (or gal) is vital to keeping the software power in the hands of the people, where it belongs.