To Learn C or Not

by Krishna on June 1, 2008

The past few weeks, I have been listening to the podcasts of Joel Spolsky and Jeff Atwood at The discussions are perhaps not as informative as a Hanselminutes podcast, but they are definitely entertaining and cover many topics related to software development. Atwood has posted some of the discussed topics on Coding Horror. One of the subjects that caught my attention (and others as well) was the fact that Jeff did not know the C language and didn’t feel that it was necessary, while Joel holds the opposite view.

This debate is different from most language fights. Most of them are about which programming language you must use. Here, no one is suggesting that you use C to replace your current programming language. The C advocates recommend that you learn C to gain a more fundamental idea of the low-level issues of programming, something that current languages isolate developers from. Since my first programming language was C, my first instinct was to agree with Joel, and then I realized several problems in my reasoning.

The first mistake was to forget the important place that C had in my learning curve. When I moved to C++, I was only learning the object-oriented features provided on top of C. The basic language structure (except for the OO constructs) remained the same. Moving to Java from C++ once again required only learning a few additional features and unlearning some of the C++ features. Thus, with every other language (C#, VB, Python, etc.), the learning process was always about trying to relate my existing knowledge to the feature set in the new language.

For a person who started with C, it is difficult to imagine how someone else could have learnt anything without the initial C knowledge. But if that person had started with Visual Basic, they would have learnt many fundamental aspects of programming (such as logical structure of programs, debugging, etc.) through those languages. And that person, when moving to other languages, would use their VB knowledge to understand and learn them.

The difference here is like mother tongues. For example, one person is a native English speaker and another is a French or German citizen who learnt English as a second language. But regardless, both can understand and speak English fluently, despite the fact that one of them “thinks” in another language.

But what about the advanced stuff? What about pointers and dynamic memory allocation? I think a fallacy here is to compare an advanced C programmer and a naive VB or Java programmer. If we look at the skills of an advanced programmer in any language, they would have the same level of understanding complex concepts, algorithms and data structures. The point being, you have to look at more than the programming language knowledge of a developer to understand his or her true worth.

I think it is instructive to look at the reasons why C was displaced in the first place by other languages. C has many peculiarities that get in the way of writing business logic. For example, different sizes of data types on different operating systems, null-terminated strings, etc. While knowing these intricacies gives you a better idea of what goes under the hood, it does not help you solve your business problems any faster. Secondly, they can even hinder learning. For example, a language that has automatic garbage collection may make it easier to learn data structures or algorithms without the C‑specific pointer and memory handling.

A C programmer may have to unlearn some lessons when they move on to higher-level languages. The advanced C programmer has a tendency to write tight, clever code, sometimes at the cost of making it incomprehensible for anyone else. The lesser C programmers ignore concepts of data encapsulation and tend to create classes that are simply a bunch of related functions that keep shuffling data around.

It is also a mistake to assume that just because a programming student has learnt C, that they have somehow achieved a state of greater understanding. It is possible to write non-trivial large programs in C while staying away from complex constructs (in fact, it may make for less debugging even if it introduces inefficiency). A bad programmer can also make bad mistakes with pointers and memory allocation, and have a program that runs correctly for many different test cases and for long periods, just because it didn’t hit the error conditions.

The final fallacy is a generational problem. The older generation always feels that the younger generation have had it easy so far, and because of their inexperience with failure, they are on the verge of making some colossal errors. The idea goes like this, “We suffered. We learnt the hard way. And that is why we are successful today.” Hence, there must be something wrong with the success of the new generation. Maybe they are just lucky. This argument, of course, is not unique to programming.

But perhaps, it is possible that maybe you don’t have to fail before you succeed. Maybe you don’t need to go through all the hardships and sacrifices suffered by the people before you. The new generation can start programming in their simplistic programming language and still create works of wonder without ever knowing one hardware term. Maybe the rules have changed.

At some level, I think people understand this. But there is a real sense of nostalgia that believes that the new generation will never get to experience what they had. The feelings of achievement on solving a complex problem. The respect and love for the programming profession. The constant quest for learning. The acquisition of minor trivia. The knowledge that makes inside jokes funny. But this sense of loss ignores the fact that different people can reach the same goals by different journeys.

A real programmer is always on the lookout for improvement. Some of them, who started with a different language, may choose a path where they go back and learn C, maybe even contribute to projects that require C knowledge. Others may choose a different path where they learn about new languages or techniques. In the end, I think what matters is not what a programmer knows, but what and how quickly he or she can learn, and how well he or she can contribute to solving real problems.


Kalpesh June 2, 2008 at 8:50 pm


Good to see a post.
Your last line sums it up well.

If you want to drive a car well, you should know its internals. IMO, C comes in that category. Some people know in/out of things & it helps them understand how it works & how things can be better utilized.

For some other people, it is a means of transportation & having to know some internals is fine.

It all depends on which angle you are looking at things from.

C is suited to low-level, super power things. It might be difficult to write an OS in c#. Having learnt C, it helps understand (again depends on what/how much someone is willing to learn) how things work under the cover.

There are obvious benefits of learning C. But, do you need to worry about those? There are some companies which abstract you from having to worry about memory management & write garbage collector, so that I could think of business problems.

Well, we haven't yet reached that stage (we still worry about the level below which we are working)

Krishna Kumar June 3, 2008 at 8:22 am

Well said, Kalpesh

Although we haven't reached the stage where we don't have to worry about the low-level items, the need is decreasing as time goes by.

Comments on this entry are closed.

Previous post:

Next post: