I was involved in a discussion recently regarding the relevance of C in modern programming, and I found one person’s comment both intriguing and alarming.
“Please don’t tell people to learn C. It’s our grandfather’s language.”
He wasn’t the first person I’ve encountered to make this argument, and I know he won’t be the last. It reveals a dangerous attitude which is increasingly prevalent in the programming industry, and I’m not the first to notice it.
Oh lookie, a new entry for A Field Guide to Common Nerds!
If you’re among this group, please put down your pitchfork for a few moments and hear me out.
Programmaticus Trendicus, perhaps more succinctly identified as Trendites, assert that we are in a new era of programming, where the tools work for us, and we never again need to descend to those clunky, old fashioned languages of yesteryear. I will credit them with largely positive intentions – they want to save masses of programmers the pain and agony of covering old ground unnecessarily.
I won’t even touch on the various hostile hybrids of this species and focus instead on the purebreed P. Trendicus. Suffice it to say, when combined with P. Newbieflamerous or P. Militaricus, the result is the stuff of nightmares.
The Trendite’s assertions, liberating as they may seem, are misguided at best, and hazardous at worst. The basic premise of this worldview is that lower-level languages like assembly and C are no longer needed. We have moved to better, easier, and more powerful tools like Python and Java that allow us to do everything with less muss and trouble.
At this point, let me lend credibility to part of this assertion: C is clunky, dusty, and annoying as heck. This is even more true of assembly languages. Even C++, the relevance of which is hotly debated among Trendites, is an elephantine kludge compared to light and nimble “modern” languages like Python and Java.
I’m a loyal Pythonist to the end. I love that language, and frankly bemoan the fact that I get to spend so little time in it due to work obligations. In fact, I would say that if you can effectively accomplish your task with Python, Java, Ruby, Haskell, or any other language of that sort, you really should! There isn’t much point to tormenting yourself with a lower-level language unnecessarily.
With that in mind, let me also say that C++, C, and the assembly languages are relevant and essential tools in a programmer’s toolkit. I’ve even gone as far as to say publicly...
There is a very good reason I tweeted that.
For one thing, many languages are built on top of C, and ALL are built on top of Assembly. As I mentioned in my article The Cake Is A Lie, layers like this are not entirely stable. Sooner or later, something in the foundation will crack, and the upper levels will start crumbling. Think about how many instances of bizarre, inexplicable behavior occur in those higher level languages. More often than not, it stems from some undefined behavior (roughly, a situation in which the C language has no appropriate response built in) in the language’s C source code. This undefined behavior mutates further as it propagates up through the layers, and next thing you know, Python is dancing on the rooftops in its knickers.
Let’s imagine for one moment that the Trendites succeed in their mission, and there doesn’t remain a single programmer on earth who knows C. Once someone sees Python doing its rooftop jig, who do they call? Python’s C code could never be fixed. The bug would exist permanently, and as is inexplicable tradition among computer bugs, somehow get worse.
Taking a step away from programming for a moment, we can easily draw a parallel between C and the combustion engine. The Trendite’s argument is equivalent to telling engineering students “we already have so many good engine brands. Don’t learn how to build an engine, just get a pre-built one and put it in your vehicle.”
Obviously, there are three problems with this: A) if an engine breaks, no one is left to repair said engine. B) an engine can never be made more efficient than it already is, and C) innovative new sorts of vehicles can never be invented, because no one knows how to design an engine to meet that vehicle’s unique needs.
This does not dismiss the reasonable argument that your average mechanic should not build an engine from scratch for a Toyota Camry when a pre-built engine can be purchased and installed. It would be a waste of time, money, effort, and risk (what if it isn’t built right?) to custom-build an engine from scratch. That reality does not invalidate the need for people who can build engines; in fact, that mechanic would probably be far more effective if he had built engines in the past, because he can diagnose problems and avoid unnecessary replacements.
That’s the second reason why C++, C, and assembly remain relevant. Although a programmer may spend 90% of their time using Java, Python, or the like, their knowledge of what is going on “under the hood” in C and assembly help them to write effective, efficient, quality code. The discipline of writing good, solid C code – an arduous task – carries over into all their other programming work. Instead of hacking their way around a solution, they know what they want, how it works, and exactly how to get there.
This is why I say that a programmer must know C to be considered a true professional. Python and similar languages do so much for us automagically that we can easily become flabby armchair programmers if we aren’t careful. I’ve seen it happen so many times – I’ve broken in several Java programmers, and there were a lot of lazy habits they had to conquer. Those habits were not formed as a result of any character flaw or inherent apathy. They had simply never known the habits were problematic (or present), on account of them never coding in anything lower-level than Java.
“Okay, granted, but those habits really don’t mean anything if we’re in Java or Python!” you say.
Are you sure about that? There is a profound difference between working code and good code. Working code accomplishes the task by any means necessary, but it can often be by a sheer brute force approach, which is not efficient, pretty, or easy to maintain. Good code is written to solve a specific problem in an efficient and elegant fashion, and while there are many ways to write good code, brute force is rarely one of those ways.
The little idiosyncrasies of C and the like force the programmer to think through their solution carefully, and come up with the best plan of attack. Unlike in higher level languages, brute force in these languages usually yield exceptionally slow, error prone programs that beg to be fixed. Bad habits become immediately apparent.
In short, mastering C is an effective way to short-circuit the lazy habits in our minds and establish the practice of thinking through our code. We are programming in the trust intellectual sense of the term.
One can parallel this with the idea of learning how to drive a stick-shift car. You have a better understanding of handling, and you have more control, especially in treacherous driving situations. In addition, driving an automatic only requires one to remember that the car does many things for you.
Conversely, if one only knows how to drive an automatic, they’ll likely have a harder time driving in bad conditions, and will have a far harder time learning a stick-shift later, if they take the time to learn at all.
Just as one may argue that the sooner one learns to drive a stick-shift, the better (and easier), one may argue the same for learning C. The longer one waits, the more entrenched the bad habits will be when they begin.
With the case for lower-level languages in place, let’s revisit our friend, the Programmaticus Trendicus. When fully grown, a Trendite begins to value the “trendiness” of a language or toolkit over its efficiency. They’re addicted to syntactic sugar, those little programming language features that make it easier to write code (and by extension, to write bad code). Their software is bloated with inefficiencies, and easily takes up excessive memory and disk space. In many cases, their resumé is likewise bloated with the names of brand new technologies that no one has heard of and few of which will remain “relevant” for more than a fortnight. Thankfully, many Trendites are not this deeply entrenched, especially when they are young programmers. There is still hope.
C++, C, assembly, and other low-level languages are not relics of a bygone era. They are the most essential tools we have, upon which everything we rely on is built! It is only because they exist that we have the easy, trendy languages like Python, Java, Haskell, and Ruby. It is only because programmers still learn how to master C and the like that we continue to see new and better tools and languages emerge.
It’s ironic, really. In their often well-intentioned efforts to further progress, Programmaticus Trendicus is in danger of stalling progress completely.
UPDATE: I want to emphasize that there is a definite case for phasing out C as a low-level development tool for new technologies. There are alternatives, including Rust, that can be considered. However, as long as C code exists, I believe my points still stand.
If you are now convinced that C is the next thing you need to learn, I personally recommend Zed Shaw’s Learn C the Hard Way, a newer publication which approaches the language from the perspective I described – mastering C to become a better programmer in other languages.
Top comments (7)
A very good discusion, with plenty of good points. To make maintainable software, it doesn't pay to only focus on the highest level of abstraction.
The sentence "This is why I say that a programmer must know C to be considered a true professional." did make me cringe though. The problem with that is that a programmer can very easily be extremely productive and create very maintainable code without knowing any C. A true professional uses the tools required for the job at hand, and makes sure that he uses those tools properly. That may or may not include knowledge of C.
To put it into perspective, it would be equally valid (i.e. not) for me to say that no C programmer could be considered a true professional without being sufficiently adept at old-school electronics as well as the underpinnings of quantum mechanics (with a particular interest in quantum electrodynamics), since that's what all of it fundamentally runs on.
(Edit: notably, there's a sizable difference between a skill not being needed in general, and it not being needed in every single person -- it's the splitting up of skill sets among individuals that has served as the engine for much of human progress, since the times in history when one person could possess all human knowledge are long gone)
I think I understand where you're coming from. I rarely make statements like "a true professional must X". My motivation on that one exception was that it is hard to really understand the underlying mechanics of programming without knowing C. That knowledge of underlying mechanics is generally critical to writing clean, well-performing, efficient code.
That said, it could be argued that knowing any number of similar low-level languages with such low-level control can substitute for knowing the C language. For example, if one were proficient in Assembly, they could absolutely skip C in terms of the fundamental knowledge it provides.
The trouble is, we have too many programmers who just "leave the fundamentals to the mega-nerds", and crank out garbage as a result. They don't actually know what they're doing, why they should use certain algorithms and design patterns. Even if someone can leave the low-level work to others, they shouldn't be in the dark about it.
There are "good" programmers who know C and there are "bad" programmers who know C. There are also "good" programmers who don't know C (or any other low level language).
To make your case you'd have to take a group of "bad" programmers break them into groups and run experiments on each group. And then come up with the result that the only way to turn them into "good" programmers was for them to learn C (all other treatments failed). If that turned it to be true, I'd be very suprised.
I know there are a lot of "bad" programmers out there but I think their level of C knowledge is a non-casual factor. Do you know of research that suggests otherwise?
Tsk tsk ...darn kids ;)
You would notice that! XD
:D
Psst, another good angle on this is Hype Isn't A Use Case - which is the article that reminded me to post this one!