In most computer science programs, the first course in the sequence is a basic programming course. Usually, this course introduces the standard concepts, along with one of the more common programming language. And at least from what I’ve seen, that language is usually C.
From what I’ve seen in the classes I’ve taken, and particularly from what I’ve seen tutoring at the college this quarter, this is a mistake. Don’t get me wrong, C is a great programming language. I learned on it. I like it. I use it regularly. But as a first programming language for beginning students it leaves a lot to be desired.
The problem with C is that it’s a rather complex language. In many respects, it is like a higher-level version of machine assembly. This makes it well suited to advanced projects, but quite problematic for people who are just beginning to learn the principles of programming. At a time when they need to be learning the basics of how to decompose and analyze problems, they are forced to deal with grapple with the often opaque and unintuitive mechanics of the language.
The main skills that beginning programming classes need to teach revolve around problem solving. How do I approach a complex problem? How do I split it into more manageable subproblems? How do I go about building a solution? Obviously, they do need to learn a programming language as part of the process, but to me, a good understanding of how to construct an algorithm is far more valuable early on than a good understanding of pointers and computer memory architecture.
What I’ve seen with the students I’m tutoring at the introductory level is much of their time is spent grappling with the mechanics of functions and pointers in C. The assignments they do generally focus on those mechanics, so they have a chance to practice. What they often seem to lack is a notion of how to approach a problem, especially if the assignment does not lay out such an approach in detail. The downside is that much of my time helping them is spent going over the language, not over more generally applicable skills.
To be fair, none of the languages I’ve used seems truly appropriate to that task, but to me C is definitely among the worst possible choices. Java and C# may not be perfect, but they do at least shield users from some of the details that aren’t really relevant to programming as skill. I’d be inclined to say that in many respects, a general proof-based mathematics course is more valuable than a C course, since it really does give insight into how complex problems can be solved using simple pieces, and how algorithms can be arrived at. A background in rigorous proofs also tends to give a better appreciation for logic and careful reasoning.
Now, with all of that said, the same things that make C problematic for those just starting to program makes knowledge of it a must for almost all advanced programmers. You can’t fully learn C without understanding the underlying architecture of modern computers. And if you need to take full advantage of that architecture, C is usually the language best-suited to it.
In short, C is a good language. It’s just not a good language to learn on. First learn to walk. Then worry about signing up for the marathon!