122 comments

[ 3.2 ms ] story [ 176 ms ] thread
I'm surprised that people have managed to get through a CS program without learning C (or, at least, C++)! It seems to me that programming should be taught simultaneously in Haskell (or Lisp?) and C.

- C teaches you how computers work.

- Haskell teaches you how programming logic works.

Probably because some modern CS programs use Python for their intro courses and Java for the advanced ones.
That's about right, I think. Mine started with Java (because the school was heavily supported by Sun). Some more advanced courses went into other styles of programming (Prolog for logic programming, Lisp for functional, ARM+MIPS assembly for low-level understanding). The C++ courses were purely electives and were taught in a "C with classes" style when I took them around 2005.

Of course the compilers, networking, and robotics classes all assumed fluency in C, and of those, the series on compilers was required, so it was impossible to escape learning at least some enough C to pass those classes.

C doesn't really tell you how computers work, a healthy dose of Hennessy's book and an accompanying lecture works much better than learning C.

But C has immense cultural value. Lots and lots of extant source code, important source code: Linux. The BSDs. PostgreSQL, SQLite, whatever.

C is the lingua franca. "Everybody" speaks at least a little C, so it can be used as pseudocode notation (without learning some specific, maybe even ad-hoc, pseudo language).

> C has immense cultural value. Lots and lots of extant source code, important source code

Yes, exactly! In my opinion, C for a programmer or computer scientist is like Latin for a medieval scholar. You don’t need to speak it fluently, but it’s good to know enough to read other people’s works and understand how concepts are expressed.

In practical terms, I think that almost any programmer can benefit from reading K&R and doing the exercises in it, even if they never go on to write “real” programs in C. The book is very short and readable, and finishing it is a much tinier task than learning the standard libraries and toolchain options and best practices and all the other stuff you need to be productive writing production-quality code.

> a healthy dose of Hennessy's book

Most any CS book seems to have been written in C, Java, C++ and lately, Python. Are there books on computer architecture, algorithms, compilers, whatever written in Scheme?

I have no idea what you're talking about.

Are you interested in finding such a book? Do you try to refute any of my points? If so, which one?

I am not refuting. I was actually asking if there are CS books written in Lisp. Almost any CS book I've seen relies on C, C++ or something along those lines.

> Are you interested in finding such a book?

Yes.

Ah, okay.

Off the top of my head, only Structure and Interpretation of Computer Programs. But that's... different.

And Paradigms of Artificial Intelligence Programming.

Start with "Structure and Interpretation of Computer Programs".

Google it -- it's freely available on-line, along with a video lecture series.

It's different, in that it doesn't teach Scheme (Lisp). It teaches computation (aka CS).

Go from there.

> Most any CS book seems to have been written in C, Java, C++ and lately, Python.

There are plenty of CS books where the code targets Scheme, another Lisp, or another functional language (e.g., ML or Haskell.)

University textbooks with Scheme/Racket as a primary language for examples/exercises:

- Structure and Intepretation of Computer Programs (SICP), used for decades in MIT’s introductory CS course: https://mitpress.mit.edu/sicp/

- Picturing Programs: http://picturingprograms.com/

- How To Design Programs: https://en.wikipedia.org/wiki/How_to_Design_Programs

- Programming Languages: Application and Interpretation: http://cs.brown.edu/~sk/Publications/Books/ProgLangs/2007-04...

C was the first official language I learned in school. It was very hard at first, mainly because I couldn't see how everything (memory management, pointers, references, data structures, etc.) would fit in a real world scenario. We didn't learn about Make and building automation until 3 months in the course. `gcc myfile.c -o myfile` was all we did, one concept at a time.

Maybe programming 101 should start with a higher level language and dive slowly on "how does that work?".

I'm of the mind we should be teaching predicate and temporal logic, formal methods, and critical thinking before teaching languages.

Though if you were to start with a language C might be a good one just to show you how sloppy thinking leads to incorrect behavior and poor performing programs.

I think you are absolutely right.

This will (apparently) never happen. I actually had a conversation with the mathematics department chairman about this after I took the formal logic course as a junior in college. "Why wasn't this the first course I took?" I made A's on all subsequent math courses; I'd been a lot B's and C's up to then.

He didn't say he knew why we don't. Now, this is a smallish college that started as a normal school - a teacher's college - and still is a teacher's college. The only graduate courses there were in education.

I think we all actually know why. We cargo cult these things to a deep level. I don't think it's intentional; I think that very few people know what rigor and formalism are. It's painful to learn.

> - C teaches you how computers work.

Except it doesn't. If any language "teaches you how computers work", its assembly. While a lot of the quirks of C's design compared to more "pure" structured programming languages (e.g., Pascal) reflect a desire to provide more direct access to common low-level features of systems of the time when C was introduced, it doesn't really teach you how computers work except insofar as trying to understand its quirks might motivate some inquiry into how computers work.

Agreed. I would say that C teaches you how the OS API works. That doesn't map well to how even a simple computer works, let alone one with multiple processors, complex memory hierarchies, north and south bridges, various I/O adapters, etc. Don't even get me started on anything virtual or distributed. Knowing C might help, to the extent that code which might be useful to gain such understanding tends to be written in C, but the language itself isn't going to impart those lessons.
I am a strong believer in learning C as your first language. Why? Well a number of reasons but the two main ones are 1) it teaches you about what is happening at a lower level so you have some idea about what is happening behind the scenes of that Java code you wrote or whatever and 2) it makes you appreciate just how lucky you have it in higher level languages.

However I don't think you should start writing all your programs in C! Use the right tool for the job. If that job is something C makes sense for then go for it but if you are writing a webapp I wouldn't recommend you use C (although I would if you needed a fast, native library to call from your webapp).

> although I would if you needed a fast, native library to call from your webapp

Honestly, at this point you're probably better of using Rust for that.

Until not too long ago, De Anza College still taught C as an introductory programming language (I think because some recently retired instructors wrote a textbook on it). Even now, from what I've seen of the syllabi online, their C++ course that replaced it is still mostly C with some sprinkling of classes added on.

I thought it was a horrible idea, and I had a pretty miserable experience at De Anza. If you're just starting out programming, you should simply get used to writing code, and not fighting low level details of the language. C is the kind of thing that is useful, perhaps only as an advanced undergraduate course. Most beginning programmers need to start writing code, not get bogged down in pointer hell. And obviously most beginning programmers aren't going to be hacking away at *nix kernels or anything advanced like that.

I agree. When starting out with programming, the most important aspect to learn about is the program logic. Syntax and implementation details that are not strictly necessary just get in the way and are likely to confuse students. Once you're comfortable writing algorithms, then you can move onto languages with more complex syntax and features.

That said, you could do a lot worse than C for an introductory programming language.

My university used Scheme (a Lisp derivative) as the first programming course language, and these were some of the reasons why I found that an excellent choice.

Some other points being that most people start on the same level, and functional languages allowing the construction of many concepts that are not part of the language itself.

My experience is the reverse. I think that beginning with C gives you the necessary knowledge of the inner workings of programs and systems that is required if you want to end up with a degree in CS/CE/similar. I've seen too many programmers that started with Java or Python and then didn't know what exactly is memory, what is "allocation" or similar concepts that are required if you want to understand what's going on with your programs.
I do think C is a very useful programming language to learn. Certainly, concepts like memory and pointers can be crucial knowledge. But I disagree that C needs to be a programmer's first language. I've seen plenty of programmers who started out with Python or Java, then later went on to learn C and were none the worse. I myself started out with Visual Basic. Just because you didn't start out with C doesn't mean you can't subsequently learn it and low-level concepts.
If you're going for a full-stack CS or CE degree, yes: start with a low-level near-bare-metal language and work up from there. One may need Java et al to initiate interest in such details, but once the path is started get down to basics ASAP and build up from there.
I agree. Furthermore, I think pointers in C is a simple concept that becomes incredibly powerful, and also gives a lot of insight into how memory works and the different data structures.
> not get bogged down in pointer hell

No one should get bogged down in pointer hell. I program C for real work all the time, and I teach it to undergrads, and we use pointers carefully and with awareness. We don't do arithmetic or other 'clever' stuff. And we don't get bogged down in pointer hell.

Why do we teach it to undergrads? Among other reasons, because trying to teach OS or compilers to students who don't get pointers or any other low-level stuff is miserable.

The whole handmade thing seems kind of silly. Yes, understanding what's beneath abstractions is important, but if you want to build software well, you should use your abstractions well, because not every piece of software needs lightning speed.
I don't think the author is arguing everyone should use c for everything. He is arguing that everyone should write something in c so that they understand the abstractions they use better. Abstraction is great because it let's you build your conceptual structure atop a virtual foundation, but your structure will be more grounded and therefore more sound if you learn to connect your understanding of the virtual foundation to its physical origins.
Yep, exactly. Abstractions help make us more productive, but if we don't understand what it is they're actually abstracting, I believe they're limiting us, not enabling us.
I'll toast to that. No, I was talking about the "Handmade Manifesto" that you linked to, which seemed to say that high-level abstractions are EVIL.
While I agree with this in theory, I can't help but imagine that 20-30 years ago you could take this post, replace every instance of "C" with "assembly" and it would relate to a lot of developers at the time.

The march of technology (and knowledge in general) is one of constant abstraction. We figure out ways to do more with less so we have more capacity left over for further advancement. You don't know 10x10=100 because your brain derives it every single time, you just memorize the fact, hopefully with understanding. In software terms that means higher level languages with sophisticated libraries, and languages like C are relegated to more of an infrastructure role.

This isn't necessarily bad. If the technology is more capable then everybody wins at the end of the day. As the author points out there will always be a niche of enthusiasts/zealots who will lead the charge and further the field. The remaining 99% will learn what those people come up with and apply it. To the best of my knowledge that's how it's always been, and it's worked pretty well so far. So I'd say let people start off with high level languages if they want, but expose them to lower level languages and let them choose which demographic they end up joining.

I find it odd that anyone would question the value of learning C. I find the negative attitudes toward C to be very odd in general. Now, it is clear to me that I am in the minority, but I can't understand why people would be doing serious work in an interpreted language. I detest garbage collection as I have no control over it. I am sure I could write statements like this all day.

Don't get me wrong: I use perl when it makes sense; I use Java when it makes sense. I quite like playing with new languages and seeing what I can do with them. There are many languages that are safer than C or easier to do particular tasks than with C, but I am very rarely happy with the trade offs. When I am trying to do serious work that is meant to stand the test of time, I'll use C.

> I can't understand why people would be doing serious work in an interpreted language. I detest garbage collection as I have no control over it.

You have no control over C's register allocator. (Well, very little, `register` doesn't mean much.) Assuming you use it, you have no control over how the standard library's malloc() and free() work. malloc() could be best-fit, first-fit, something else entirely, who knows. No control over fragmentation. You have no control over the CPU's branch predictor or cache eviction policy.

You don't control the OS's thread scheduler, virtual memory implementation, etc.

Everyone picks a spot where things below that level are details they don't want to care about. You may have picked a slightly lower level, but there's nothing fundamentally different between you liking C and someone else liking Java (which is GC but not interpreted), Forth (interpreted but not GC), or Ruby (GC and interpreted).

People do serious work in Ruby for the same exact same reason you do serious work in C, it lets them control the things they need to control and ignore the things they don't.

Exactly. If I don't need to care about X, picking a language where I don't have to care about X is a win (for any value of X).

That is, it's a win right up until the scope or scale grows to the point that I now have to care about X. Then the language where I "don't have to" usually turns into a language where I can't, and I'm trapped.

Yes, but interpreted is slow, and garbage collection causes pauses at essentially random times. These things are fine for one off sorts of problems where it doesn't matter much if it takes a little longer. If you are writing an application that is meant to be run thousands or millions of times, I start to wonder why people don't care more about these trade-offs (the answer is, of course, they do . . . if they are, for example, running large infrastructure like Google or Amazon).

My point isn't/wasn't so much to crap on other languages, but to express dismay at why people crap on C so much or view it as irrelevant. Ruby is definitely not irrelevant. Why would people think C is?

The main language at Amazon is Java. Lots of Java code is being run millions and millions of times there. Java isn't as slow as you think it is.
I didn't say Java is slow. I said that garbage collection introduces unpredictable pauses. This is potentially an issue with Java, but it all depends on the problem you are trying to solve. In many cases, it won't matter, but in some, it will.

How is this relevant to the idea that C is an important and relevant language?

> My point isn't/wasn't so much to crap on other languages, but to express dismay at why people crap on C so much or view it as irrelevant.

Well... you did kind of just crap on other languages.

Personally, I like C, C++, Java, Ruby, JS, and lots of other languages, all for different purposes. I don't feel dismay when people use GC languages, or when they use languages that make it easy to have buffer overflows or security bugs.

I just get dismayed when they use them for the wrong kinds of programs.

Ruby, Python, Perl, PHP, Java are all (mostly) built in C ( not to mention most databases ). Why not learn to program in C?
The same reason I didn't learn woodworking, even though my house is mostly made of wood.

I mean, look, I'm a professional C/C++ developer, and have been for 30 years. But the fact that your tools are written in it doesn't mean that you need to know it. (I need to know it because I work in embedded systems; C/C++ is the language of choice there, even now.)

You realize that computers don't literally run C code, don't you? By that argument you should go further and build your own hardware, then write your own OS...you get the point.
I think C is a good choice to stop. I know it's an abstraction itself, but beyond that you get into hardware specifics and often-closed OS code.
> often-closed OS code.

If you use GNU/Linux, OpenBSD, FreeBSD, NetBSD, SmartOS, OpenIndiana, OpenSolaris, etc this isn't a problem.

C is great. I wouldn't recommend starting programming in C, though. At least not with the standard exercises you see. Get user input, read a file, do this do that with it.

Why? the C standard library is full of gotchas and tricks and goofy shit that makes it unsuitable for new programmers. The comp.lang.c FAQ should be standard reading material for anyone taking a C class. Look at all the posts on StackOverflow about the stdio functions 'not working right' and asking how to do menial things like collect keypresses.

C works well as a first language if you teach it like assembly (use of which as a teaching language is another debate): flip some bits and do some loops. But not for collecting user input/output. Half of your students are going to get stuck trying to collect a list of names from the user, before they even get a chance to get stuck trying to sort the list.

Overcoming goofy shit and gotchas is part of any programming system.
Yeah, but why start with an exceedingly painful one except to needlessly inflict pain and suffering on students. Better to lay the groundwork with a friendlier language, learn the basics, and then move on to the more complicated gottchas (at least in my amateur opinion).
What language would you suggest is friendlier, and less rife with gotchas? I find the rules of C fairly reasonable, at least on the surface.
#include <stdio.h> int main(void) { (printf)("C is awesome\n"); return 0; }
#include <stdio.h>

int main(void) {

  (* * * * * * * * * * * * * * * * * * * * printf)("C is awesome\n");

  return 0;

}
In C99:

    #include <stdio.h>

    int main(void) {
        (* * & * * * * * & * * * * * * * * * * * * * printf)(&1["C is awesome\n"]-3/2);
    }
I proudly display my "Best Abuse of the Rules" category win of the Int'l Obfuscated C Coding Contest on my resume.
In no particular order any of the following as an introductory language.

Ruby -- puts "Hello World"

Python -- print "Hello World"

Lua -- print("Hello World")

Personally I wish every programmer would eventually learn C. Getting down to that low level and really understanding how things work is important, but if it is the first language I think we would end up with a whole lot less programmers as many would give up early.

Ruby is written in C

Python is written in C

Lua is written in C

I'm not sure how that is pertinent. Programming languages as a general rule are initially implemented in some other programming language and then potentially later bootstrapped with their own language.

Ruby has also been implemented in Java (JRuby), Ruby (Rubinius), .NET (IronRuby), JavaScript (Opal).

Python in Java (Jython) and .NET (IronPython)

Lua has been implemented in too many language for me to list them all here (C, C++, Lua, JavaScript, Erlang, OCaml, Go, etc...)

It seems C itself was initially bootstrapped from B which was bootstrapped from BCPL. If we were to follow this to it's logical conclusion I'm guessing we end up at some version of Assembly. Are you suggesting we should start budding programmers on Assembly?

No. Just stick with C so that it's portable and fast.
I don't write Python in C /s

You meant Ruby, Python and Lua have their reference implementations written in C. They all also have other implementations written in other languages.

That's what I meant. Most important programs are written in C. Look at what program you are running now. See if you can find the standard C library it links to.
The drop from Pascal to 'C' is pretty short.
JavaScript has been touted as an intro language, and in some ways it's even quirkier than C.
Recommending JS as intro language is just plainly wrong.
My first language was C and I loved it. Maybe it takes a certain type of mindset and tenaciousness (madness?) that will put up with the gotchas. It was exactly those gotchas that got me hooked though. It was similar gotchas that made me love Linux the terminal, vi etc ...

The argument that one "should study other languages before they're fit to learn C" is terrible IMO and somewhat condescending. It's like saying one must learn "nedit/pico" before starting with editors like "emacs/vi". Please stop repeating that - especially if you have not done much C.

I am probably too old to understand the constant hate and criticism on why C shouldn't be taught to beginners. Not everything "has to be easy". Starting with C & Linux, I always had an advantage later in my career because it was these skills that enabled me to drill deeper than those who didn't know C & system programming.

C isn't just hard for beginners because of the language but the rest of the tool-chain. If you can get over this then learning C will also teach how to debug with gdb, strace, valgrind and learning about low level system calls, and a great deal about how a program can be loaded/structured e.g.: dynamic & static linking. Also where the resources are used and how to eliminate it’s bottlenecks. What is a heap, stack or static memory? How does memory management or garbage-collection work on a modern OS? What is IPC and how do the individual system calls function & require as input? How do you compile a program and optimize it for different target platforms? How do you write Makefiles or use autotools etc ...

Tell me again which other language forces you to learn these things? You could easily build a career just on C & Linux because of this "additional learning curve" and extra knowledge that a good C developer will have.

Sorry for all my bias (as I said my views might be very outdated :-))

> The argument that one "should study other languages before they're fit to learn C" is terrible IMO and somewhat condescending.

I think I agree.

> It's like saying one must learn "nedit/pico" before starting with editors like "emacs/vi".

It's very little like that. Other languages have their own strengths in a way that nedit/pico do not.

It sounds to me like you haven't spent much time trying to teach a class to program. Most introductory courses these days focus on trying to teach students to understand how to solve problems (usually to some degree agnostic of language) and then how to turn their solution into code. The largest mental leap seems to be with the former, and using C as a starting language makes the latter unnecessarily difficult compared to, say, python (which is why it's gaining such popularity among intro. courses

I can understand if one is a) very motivated and b) has the right mindset to properly frame their ideas at the low level c operates at, C could be a good starting language. But this is not the case for many beginners.

>Most introductory courses these days focus on trying to teach students to understand how to solve problems (usually to some degree agnostic of language) and then how to turn their solution into code.

The "to some degree agnostic of language" part has been available for a long time in computers, initially as flowcharts and later as pseudocode.

>and b) has the right mindset to properly frame their ideas at the low level c operates at, C could be a good starting language

That requires prior knowledge and practice more than a mindset, IMO.

I agree with this sentiment. In my experience, it's hard enough for a novice to learn to reason through basic control flow (loops, functions, variable assignment).

Over a few years of working as a teaching assistant, I saw two types of students: those that had some prior knowledge and effortlessly picked up the concepts, and first-timers that had to put in serious effort to stay afloat. If you were in the former camp, it's hard to envision how the latter might feel, and why every bit of additional complexity is a menace to someone who's already struggling with frustration over internalizing the basics. If you add too much complexity, the novice becomes discouraged, gives up trying to understand, and simply tries to memorize - this is always catastrophic for them.

As an example, I'm taking about students that write code like:

  if(x == true){
      y = true 
  } 
  else if (x == false){
      y = false
  }
Learning to program is about solving problems using a computer. Any programming language allows this, however some languages make it harder than others, and C is in that category. A language like Python has very little quirks that will stump a person coding for the first time in their life; in C they'll wonder "what does int main(int argc, char argv) mean?", "why is there a & before my variable in a scanf but not in printf?", "what are 'nul-terminated' strings?", etc.

A programmer should definitely eventually learn C, but there's no reason it needs to be their first language and definitely no reason it should be their only language.

I agree it is not easy. Though I never said that it should be the only language! Emphasis was on the fact that one could build a career on C more than any other because of the additional overhead / toolchain baggage. (I quite frankly haven't met anyone who only knew C tbh and doubt such individuals exist in the industry (in a successful capacity))
>> A language like Python has very little quirks that will stump a person coding for the first time in their life

Python is great but some of the things I've come across:

  Why do some keywords use parenthesis and others don't?
  What's this Python 2/3 hubbub all about?
  What are __INIT__ and __MAIN__?
  Why do I see single, double, and triple quoted strings?
  What does the u prefix mean in u"Hello World"?
Well sure, every language has its quirks, but those last four aren't going to show up unless the person starts diving into an existing codebase, which shouldn't happen if they're still learning. The keys/parenthesis bit I will concede is a bit of a problem.
>in C they'll wonder "what does int main(int argc, char argv) mean?

They'll only wonder that if the book / course / instructor teaching them C, does NOT explain it to them. Which would be more of a reflection on said book / course / instructor than on the C language or the students.

For students who are just learning to wrestle with the programming concept, python is far superior because it lets the student focus more on what to express and when, and less on remembering silly things like curly braces and semicolons.
First, braces and semicolons are not silly. They are just a different form of syntax than indentation. (And I say that as a Pythonista of many years, who also learned and then used C a lot before learning Python.)

Second, your point may (or not) be correct, but it is at best tangentially related to the point I was replying to, or to mine.

I don't think it's tangentially related at all. The cognitive load of trying to program for the first time is quite high.

If the student doesn't have to focus on remembering whether or not you need a semicolon or a colon on switch statement cases, they can focus more on actually grokking the process of translating thoughts and algorithms to code.

>> C isn't just hard for beginners because of the language but the rest of the tool-chain.

I can agree with this, if not moreso the fact that you also have to learn the underlying system when you learn C.

For example, I 'learned' C from Greg Perry's "C Programming in 12 Easy Lessons". I was 11 or 12 years old at the time, had played around with a few other languages, but I knew C was the language video games were written in, so I wanted to learn C.

Part of the reason I wanted to buy that book was because it came with a compiler, Borland C++ 1.0. The book was also only $29.99 and was at a store in town. You'd be learning how to use functions like fscanf() but they never covered the details of 'when things go wrong'. You're missing some bytes, your file is incorrect, DOS does this while UNIX does that... You learn just enough to get you in trouble.

Sure, one book can't teach you everything, but it wasn't quite enough to give you a real good understanding of how C worked.

http://www.amazon.com/C-Programming-12-Easy-Lessons/dp/06723...

I eventually bought a game programming book and started to learn all the 'hard' stuff that I didn't even dream about when I first started. x86 interrupts, accessing joysticks and sound cards, writing to video memory...

All of this can be solved to a point by dumbing it down and using libraries. You still have to make sure you've got things like pointers down, though. You don't quite have to worry about that stuff with say, QuickBASIC or Turbo Pascal.

I think there is a bit of a "survivor's bias" in this argument (which I actually hear very often). Many people give up after they first dabble with programming because its too hard or frustrating and C is a particularly unforgiving and restrictive language (and toolchain).

The reason I think this is important to point out is that I believe programming knowledge could be more widespread than it is today but unforgiving beginning languages tend to weed out people who aren't as familiar with computers as we are.

I too think this survivor bias is kind of a key point yes. Also from my experience if I survive a steep learning curve I tend to build an elitarian view of my skills And I have seen this in most developers out their defending whatever it is they do. If you put your blood, sweat and effort into something it will stay with us. (I have seen this attitude also in others during countless flamewars on usenet when discussing the right editors, linux flavors etc, LOL ... and nobody really spends years studying something that was really hard and then gives up on it without defending it. There is just too much (self-)conditioning in the process of acquiring the skill.

In the end people will always choose the tool they're most comfortable with, whether it's the right tool for the job or not. I have no problem with this because, if there are not enough C experts in the team to maintain the project, it would be a good enough reason why a high-level language becomes the "right tool for the job".

I started with C and it took me 3 good years fooling around with other languages too to get a "good" understanding of C. Better learn with higher level languages indeed...
Which languages ?

How common is it for people to get better understanding by travelling in other programming cultures ? My personal experience goes this way but I rarely hear it.

I'm not the parent poster but in my opinion, any language that doesn't frustrate the beginner is fine. The most important thing for learning is practice and if that is not fun people will end up quiting to do something else.
I hesitated to say that, but to me the most important part is paradigm and structures/patterns. lisp will teach you untyped tree recursion and metalevel perspective. ml/haskell will teach you typed composition. prolog goal based space exploration. forth stacks. APL arrays. C/Pascal etc are supposed to teach you 'imperative' but I believe imperative is mostly a conflation of lots of things, mutable state.. at best you'll learn state machines.
I agree with you but I think paradigms are more of a "second" language problem than a "first language" problem.
You may be right. It's hard for me to really put myself in the shoes of a completely new learner.
Yeah exactly a simple language like Python, with simple rules, one way to do a thing, and not the opposite.
What I like the most in python is, until you peek too much below, the curated features that make it small yet expressive:

- tiny set of builtins: list, dict, set - literal - slices - small syntax, and canonical indentation - simple mapping between some operators and class methods

you have enough to abstract a bit but not too much without drowning in details.

Yeah and another good thing I like about Python, it doesn't force you to do object oriented. A beginner doesn't really need this. Its like if you begin with C, you'll have to deal with pointers early, and that means understanding things like memory, stack and heap allocations, safety, etc... Way too much for a new coder.
"Unsuitable" is far too strong a word. It was ok for generations to follow the K&R examples, and now it somehow suddenly became "unsuitable"? I'd say it's just "somewhat more tricky" and "got a slightly steeper learning curve", that's it.
If you start with C as your first language you're not really starting out by learning how to program, you're starting out by learning how the computer operates.

I'm not saying this is necessarily a bad thing, mind you, but it's important to note the distinction.

Using an analogy; starting out with C is like learning to drive by being told how an internal combustion engine works, and then you're asked to wire up your pedals manually and install a fuel tank of sufficient size before you're allowed to learn how to put the car in gear.

Those are all useful things to know, but you can learn them after you know how to drive, and your knowledge of either topic (driving and automotive engineering) is not in any way impaired by learning it in a different order.

Why? C is a very high level language. It is not that dramatically different from Pascal, which, in turn, is almost a pseudocode from your algorithm textbooks. You can learn fairly abstract concepts with C without caring at all about how it maps to the hardware.
This is a strawman. The author is not advocating this as a first language:

"Learning C is not necessary for everyone, but there are many posts on Reddit and programming forums with authors who feel like they’re missing something, and I wonder if this is part of what they’re looking for."

Yeah, seems to be some confusion of the title. Probably a better title is "Why learn C programming?" The article itself isn't about "Learning to Program with C as a beginning language".

And I don't know how I feel about C as a first language. I don't believe it would be worse than Java, which was the intro course at my Uni, but my first language was BASIC of all things, which is good in some respects as it really is a "Beginners" language, but both C and BASIC could encourage sloppy practices without good instruction and C especially has some gotchas.

I think that if you are going to teach someone the craft of programming (which is different from computer science) -- really teach them, you should follow what I call the Old School Curriculum. The Old School is based on the way many kids learned to program in the 80s, and the 80s version went: first BASIC, then assembly, then Pascal.

The first language you should learn should be a doddle to learn, even if it isn't very powerful. This was BASIC (or sometimes Logo) back in the 80s, but you could probably substitute Python or even Scheme today. This language teaches you concepts like these:

* Computers follow instructions supplied by the programmer

* The instructions have to be carefully worded in order for a computer to follow them (i.e., intro to errors and debugging)

* Arithmetic and mathematical operations a computer can perform

* Computers can remember things (i.e., variables)

* Computers can interact with the world (input and output)

* Computers can make decisions (conditionals and program flow control)

These are the very fundamentals of programming and it's amazing how many people haven't internalized these concepts at a deep level.

You can actually get very far with BASIC -- entire companies have been run with BASIC code. (Software written in and for Business BASIC variants was a major industry back in the 1970s and 1980s.) You can get even farther with Python. But once the learner is ready to go deeper, it's time to begin Phase 2.

The second language you learn should be assembly, which familiarizes the programmer with how a computer actually works at a fundamental level, as well as important concepts like CPU word length, memory addresses (essential for understanding pointers), program call and return (and stacks), etc. You don't have to even complete a large project written in assembly to get the benefits of this low-level, bit-twiddling learning.

Finally, the last language you learn should be Pascal. C or C++ would be today's equivalent. In this phase you synthesize the knowledge of high-level programming, structure, and control flow that you learned during your "BASIC" phase with your low-level understanding of machine details that you learned during your assembly phase. Then, the details of how and why the language works the way it does make much more sense.

So yes, to me it makes total sense to teach C -- as (at least) a third programming language, perhaps after several years of proficiency are acquired in the other two (depending on the student).

Harvard's CS50 begins with C and it's quite successful. Well, technically they begin with Scratch, but the course quickly moves into C. They get around certain barriers (you mention user input) by providing helpers/abstractions, which are gradually torn down as the course progresses.
I enrolled in my university the same year they switched from teaching C to teaching Java in the CS curriculum. As someone that learned C++ in high school I was less than enthusiastic about this change.

But what surprised me more was that the courses became more institutionalized. Professors were bettering you for a cushy career as an employee at a bank or large corporation instead of showing you how to use the computer to solve a dizzying amount of technical, social and and financial problems. I could understand a technical college emphasizing a safe, risk-free entry into a nice career but I expected better from a university.

Whenever I don't quite understand how something works in a programming language, I try to imagine how I might implement it in C. Or I look up the implementation, or write it myself. This helps me understand from 'first principles' or near enough.
I think it doesn't really matter what people learn as a first programming language. Eventually, any serious programmer will become familiar with the most common languages and paradigms, C being one of them. It may not be the best choice for beginners, but it's valid nonetheless. People can have fun learning algorithms without worrying too much about pointers and complicated type declarations. It's not like it's going to mess up their brain and prevent them from learning higher-level languages later on.
If anyone is interested in learning C as a first language, the lectures from Harvad's CS50 course make it more than feasible[0]. IMO the practical advantage of learning C first is that all other curly-brace languages become very easy to pick up.

[0] https://cs50.harvard.edu/lectures

Learning C is to computer programming what the study of human anatomy is to medicine. You may not enjoy it, but you will be dangerously uninformed if you don't do the work.
Ugh, while I 100% agree that learning C (or similar lower level language) should be a prereq for any programming job, the use of the K&R C book is idiomatic of what is wrong with C. To many people pick up that book and try to emulate what they read.

I firmly believe that book will teach you every bad habit you should never use in actual practice. 30 years ago, many of those "tricks" made sense given the compilers and computers of the time, but today your much better just writing straight clean C (for example using array indexes instead of pointers). Not only because its more maintainable, but because it often generates more efficient code due to hardware support for base+displacement addressing and compilers abilities to understand the intent and optimize the resulting code. Furthermore, code like what you find in that book is what has given C a bad name due to buffer overflows and the dozens of other things people think are the fault of "C" rather than the programming environment around it. Not the least of which is a formatting scheme that hides bugs.

So, PLEASE, if you are learning C, stay as far away from the K&R book as you can until you have gained enough proficiency to understand the pitfalls of may of the techniques taught in that book.

What book (or other method) would recommend instead of K&R? (I agree with your point, I'm just curious)
> hardware support for base+displacement addressing

Not sure exactly what you mean by the "hardware support" part, unless it is machine instruction support of some kind for C syntax. (But I thought that a basic level of support for that was present in most processors - things like base + offset addressing mode, indirect addressing via the value in a register, etc.)

But:

a[i] is equivalent to star(a + i) in C. (The K&R book says so somewhere, in either the original or the ANSI C edition.)

And star(a + i) is equivalent to star(i + a), by commutativity (a mathematical property) which is equivalent to i[a]. [1]

So you can write any of the above 4 expressions equivalently. I verified it by writing and compiling such code after reading this in the K&R book years ago; still remember being surprised until I saw the logic made sense.

[1] Or at least, it was so, some years ago, not sure about in C99 and such.

I used "star" instead of the asterisk symbol in code above because the actual asterisk turned following text to italics - HN markup.

> Not sure exactly what you mean by the "hardware support" part,

Yes I should have been clearer, and said no penalty or minimal penalty, support for base+offset address calculation. A fair number of machines a couple decades ago, had additional latency or throughput penalties for addressing modes that required address calculation. This is still true in some cases for more complex calculations. So the use of pointer arithmetic was in many cases noticeably faster than using array syntax even though they are functionally the same. This was also partially due to the compilers not being smart enough (or not having enough registers) to dedicate one explicitly for the resulting address (and using register indirect) if the programmer was using a base[offset] calculation.

For example, the ARM I'm using at the moment has a 1 cycle latency penalty for certain scaled displacements. This means that if your looping over an array of 16 bit ints it will be faster to use a pointer to the integers if the compiler fails to increment the index by 2 and instead uses a (base+offset * 2) load/store. This means the compiler has to be fairly smart about code that uses the index's absolute value as well as its "offset" value in an array.

(BTW the particular ARM in question does base+offset*4 or 8 at full speed).

Got it now, thanks. Did not know that.
While I agree with the premise that it is important to know C, I also agree with many of the comments here suggesting that there are other better first languages out there. As a recent college grad ('15), my intro course was in Python and then the next course was in C. Python was easy to jump into--it usually just made sense and worked. While learning about loops, lists, strings, etc, that was useful. Equally useful was then moving to C and getting a better understanding of the "lower level" (especially in the sophomore computer systems course). But you don't have to understand caches, page tables, and threading to jump into a first programming class and master the principles.
C is a beautiful and pure language. It is like the Latin of programming languages. I recommend everyone to at least learn it.
A language can be beautiful, pure, or Latin, but not all three.
I liked having Ruby as a first. The REPL made it easy to see what was going on (even if I didn't understand it), the community's like for testing is fabulous, and I became comfortable doing things at the command line.
One of the best academic decisions I've made as a student was to take a course on Operation Systems in C. I did take a beginners course in C previously so it was an intermediate class.

Nothing compares to spending hours and hours grinding through thousands of lines of C and building your own passable OS from a skeleton kernel. It was the hardest course I've ever taken in college and it was my favorite.

I can honestly say I'm a better programmer and engineer after that experience and would recommend anyone to take a course in OS (hopefully in C), and you'll know what I mean.

I took a very similar sounding course at Purdue (CS 503) and would second all of these sentiments.
Why do so many people seem to think the author is advocating that you learn C as a first language? Did you read the article? He explicitly says the opposite:

Does someone brand new to programming, who’s excited about making changes in the HTML on a page or setting up a blog to later customize, or just wants a slow introduction to more complex topics, really need to worry about cache coherency? Or threading? Clearly that’s a problem for down the road. Maybe that’s a road that some developers will never need to walk down at all, depending on their focus.

His position is that, while C may not be the best language for everyone coming into programming it is beneficial to learn it eventually because it allow you to peel back the layers of abstraction underneath all of the goodies in your high-level language. This allows you to better understand and reason about even your higher-level code and opens the door to fixing and understanding a lot of things that would have constrained you previously.

I completely, whole-heartedly agree. We don't always need to be able to plumb the depths of our abstraction stack. I don't believe it is necessary for a beginner. But having the ability to go up or down in the stack is extremely valuable. C is worth learning.

It's funny how the comments went down that road. I don't think C is a good choice for a first language. I would argue that C++ is an even worse choice than C, but that's for another article...
You can write very C-like code inside of Java or C++. Just write one class and stuff all the variables and subroutine methods inside it. Many years ago I had to fix some bugs in such "converted" code. The programmer just wrapped old C code into one humungous dummy class.
I'm the author of the article.

I don't think C should be the first language for most new programmers. The article doesn't recommend that. Rather, my argument is that C provides the lowest level abstraction that (most) modern programmers could ever need. By understanding C, you give yourself the ability to break into the black box of any higher-level language or framework. You're not at their mercy if they provide odd abstraction layers or bugs in their code.

It seems to me, at least anecdotally, that beginner programmers using C feel like they can't do as much as other beginners using languages like Python or Java. Often this is because graphics are so much faster to get to when working with the libraries that those other languages offer. Without a standard graphics library, C feels like the weaker choice. How wrong that is, but I've heard this sentiment from several different beginners.

I think part of what draws me to the Handmade Dev community is that we are finding so many people who know how to code, but want to feel more in control of their programs. Many people following my Handmade Quake project have told me that they're considering learning C for the first time ever. Maybe that's a good position for C to take in 2016 - a language to learn once you've learned your first language and some simple logic but want to understand the hardware better, or figure out exactly what code is running when you turn on your Python interpreter. I hope the community is able to plant that seed in the minds of as many programmers as possible.

In my college here in Lisbon, almost all the courses that you did were in C, Programming 1 and 2, Operating Systems, Distributed Systems, etc etc, except for OO classes. They changed it to Python after i left but i am glad that i had the opportunity to learn C, although i don't use it very often in the "working world". I reckon that Python is a nicer language to a freshman that has never seen code before, but they should of kept stuff like OS and Distributed Systems in C.
C is an abstraction. Assembly is an abstraction. Even physical transistors are abstractions. You can go down the ladder as deep as you wish, there is no bottom. (Sure, you can delude yourself you that X is the fundamental level of Y... as long as you define Y properly.)

In this grand scheme of things, C is not better than Python. I don't mean the we should avoid going deeper. I mean that each level of abstraction has its own benefits.

BTW: How many of you started learning natural numbers not from counting fruits/blocks/candies, but from the ZF set theory axioms and the von Neumann construction?

>How many of you started learning natural numbers not from counting fruits/blocks/candies, but from the ZF set theory axioms

Ha ha, good one. I don't even know what the ZF set theory is. Not putting down theory either in general or in this case, of course.

Zermelo-Fraenkel set theory, an axiomatic set theory that basically forms a logical "foundation" for math. I think this comparison of counting blocks to zf set theory is super hyperbolic and not accurate though.
Thanks. Will look it up.
It is a hyperbolic, but not far from "Python is magic, C is real programming". (It would be more like "Python is magic, Turing machine is real programming".)
Interesting. I havent' delved quite much in to C but no doubt I will try to get more in to it during my spare time. IT's a good basis that some other high entity languages drew their cues from