
What’s to love about C? - nkurz
http://mortoray.com/2012/06/11/whats-to-love-about-c/
======
dkhenry
I am going to make the bold claim that everyone should know C. Even in a world
where we can do 90%+ of our coding in a higher level language we still aren't
at the place were we can get past writing out performance loops in C. Case in
point my company recently needed to speed up a 128bit AND on two MySQL binary
fields. While this can be done in pure SQL implementing the function in C
saved an order of magnitude of time. Everyone is going to run into these
performance problems and until we have run times that can match hand coded C
it will in my option still be a required skill to have.

( Yes I know you can s/C/ASM , however this is a time issue eventually we may
get past needing C , but we are not there yet )

~~~
exDM69
> I am going to make the bold claim that everyone should know C.

I agree. Anyone who's going to be working at a non-entry-level job in the
computer industry should know what the foundations are built on. C still
dominates in the kernel space and other low-level facilities everyone uses. If
you don't know it, you are at a disadvantage compared to those who do.

~~~
mattmanser
Pah, 99.9% of programmers will never, ever, ever need to drop down to that
level.

Where do these delusions even come from? I think a lot of people here would
benefit from 6 months in a 'normal' company, the kind that employs the vast
majority of programmers. Just for a bit of perspective.

~~~
exDM69
> Pah, 99.9% of programmers will never, ever, ever need to drop down to that
> level.

That is true. Most programmers will not need to write code in C. But they'll
still be better and more versatile programmers if they know the language.

~~~
ZeroGravitas
Pretty much any extra skill will make you a better programmer if you disregard
the time put into learn it, so that's hardly a high bar. What about comparing
the marginal return of an hour spent learning C with an hour learning best
practices in their own particular field, whatever that might be?

------
exDM69
After using C++ for years (in addition to Python, Haskell, etc) I've recently
converted back to C for my low level tasks. You just gotta love the simplicity
of C programming. My jobs consists of reading blobs of binary and throwing it
around different buffers in memory (mmap's and dma buffers, etc), so C is a
natural choice.

I like how C is fast and dangerous, there's no silly security layers (like
Java) and it lets the operating system do it's job. Fast stack allocs for
temporary data are great but deadly if you fuck up.

Coding in C is like carrying a loaded gun pointed at your feet. You have to
handle it with care and responsibility but when you need it, you can shoot
away any extra limbs that get in the way and show 'em who's the boss.

~~~
uhhyeahdude
<Coding in C is like carrying a loaded gun pointed at your feet.> Could not
agree more. Except I would say pointed at someones head, or, perhaps, your
own.

~~~
TazeTSchnitzel
Coding in C is like being presented with a grid of buttons of various shades
of blue and green. You know to press a specific colour, but it doesn't always
do quite what you expect, and half the buttons segfault.

------
va_coder
People who love C love it, in part, because they are often solving interesting
problems with it. Many problems that require C are interesting: embedded
software, automated robots, new databases etc. Most problems that C is not
good at - Web development - are not that interesting to many people that love
C.

~~~
tosseraccount
C is not good at web development? Most of the "web" stack is written in C:
OS/NGINX/apache/php/java/perl. If you do write the top of the stack in C, it
will run faster than anything else and be smaller. This means lower turnaround
time which is VERY IMPORTANT in web apps. C, in many cases, is the best Web
language.

~~~
sgk284
In what world does runtime speed and compiled size have anything to do with
turnaround (or programmer productivity, as I read it)?

C is a great language for many reasons, but let's not conflate benefits.

~~~
tosseraccount
Perhaps there's a misunderstanding in the term "turnaround". I meant it in
this sense t = x + y + z. where t = total time, x = send time , y = processing
time, z = send back to user time. If you can decrease y, you decrease "t".
Responsiveness is important to users. With the advent of large and extremely
fast memory cache, small program size will dramatically increase program
execution speed by have small code and small data already in cache. Smaller
program executable will enable many more instances on a real physical node.
Size matters. Speed matters.

------
gouranga
The thing I love about C is that it the most obedient of all languages and
never assumes you are an idiot. Never does it tell me I'm about to blow my own
foot off - it just does it and I've learned from the experience. Due to this
it taught me how to think about things first and know of all the consequences
of doing everything.

*NIX is the same.

~~~
rpearl
The following program compiles _without warnings_ using gcc 4.7.0. The
compiler uses the undefined behavior of accessing a variable that may not have
been initialized to turn the conditional into one that's always taken, and
then folds it away.

<https://gist.github.com/2910012>

~~~
antirez
valgrind:

    
    
       ==46592== Conditional jump or move depends on uninitialised value(s)
       ==46592==    at 0x100000E90: foo (in ./a.out)
       ==46592==    by 0x100000ED3: main (in ./a.out)
    

The matter is, valgrind exists. Everything is a C deficiency that valgrind is
able to overcome decently is no longer a C deficiency practically speaking.

~~~
pcwalton
Not true. Valgrind is a dynamic analysis, while these kinds of errors could be
caught by static analyses.

------
tezza

      * Lots of programmers you can hire today (contrast to D, ML, Haskell )
      * Excellent introductory texts (Kernighan & Ritchie)
      * Backed by giants like Microsoft, IBM
      * Everything else always has some mechanism to link against it
      * Thorough API documentation (if quite large) MSDN, man 3 sprintf

~~~
dkhenry
I think its a lot harder to find good C coders then you might think. For
example 80% of people who claim to know C that interview with my company fail
a test on reading a CSV file.

~~~
kiiski
But many of those 80% probably just haven't needed to use C, or read a CSV
file, in a while. If someone randomly asked me to do that in Lisp, when I've
been coding in Python for a year, it would take me a while to remember how to
do it. But after working with Lisp for a week, I could do it easily again.

~~~
Jach
You don't even need a week if you have access to the internet, which as a dev
you will. (Or with just Clojure's repl-docs you could probably come up with
`(with-open [rdr (reader file-name)] (doseq [line (line-seq rdr)] (let [parsed
(.split line ",")] ...)))` fairly quickly, and even if you forgot the specific
reader syntax remembering the more memory-intensive `slurp` for a year seems
doable and ought to be acceptable in an interview.) If you hadn't been doing
Python for a year would you still remember the existence of the CSV module you
can import, and then use dir() and help() on if you forgot the exact syntax?

The particular example of reading a csv file is just a bad one to compare C
and any dynamic language with, because in C file IO is a pain in the neck with
a lot of pitfalls whereas dynamic languages make it lovely and you only have
to remember a small amount. I guess it's a decent test to see if one's
potential C coder has memorized all the details about C's file IO, maybe the
company does a lot of that since they create libraries for others or
something. (Did you allocate enough memory on the stack/heap? Are you reading
byte-by-byte looking for a newline or in chunks before looking? Are you
checking if you need to re-alloc? Do you support "\n", "\r", and "\r\n"? Are
you checking for E_NO_MEMORY and E_BAD_SOURCE? Are you using sprintf safely?
Are you checking for end-of-file correctly? Are you tokenizing the line
properly? Are you faster than Python? Etc.) If the interview is just looking
for coders who can "fopen, fread with malloc, and fclose, it's okay if details
are forgotten", then it's just a weeder question rather than a skill test and
there are better weeder questions.

Personally I have a handful of C programs on hand that I know are correct and
that do various IO stuff, I tend to just copy from those on the rare occasion
I need to use C to do manual file IO or memmapping (we all remember the
subtleties of that right?) because of the reasonably high probability I'll
forget one of the many details if I do it from scratch. I much prefer using
already existing libraries to read and parse for me; there's too much
reinventing-the-dysfunctional-wheel culture in C.

~~~
kiiski
I used Lisp and Python as examples because I don't know C myself. In any case,
the point was that when people say they know a technology, they might mean
that they can answer any question you can come up with, or they might mean
that they once knew it, and can become proficient with it again in a short
time. Of course, some people don't actually know anything about it, but I
doubt this number is quite as high as 80%.

~~~
Jach
I can believe the 80% number. I don't know any formal studies (surely there
have been some by now?) but I've heard and read a lot of anecdotes (like the
one in this thread) from technical interviewers about how a high percentage of
their applicants can't write code or are in some other way incompetent for the
job; I have yet to hear from one about how almost all their applicants are
awesome and they wished they could hire them all. If you haven't seen the
accounts about the FizzBuzz problem alone (and the hilarious failures of
people online with no stress or time constraints pasting their incorrect
solutions in blog comments to prove their skillz) it's worth half an hour of
your time to read about it.

------
regularfry
Ugh. Just today I've had to clean up a problem where a function was called
without enough parameters, but because the compile-and-link step included
_just the right_ components, there was neither a warning nor an error. Not
only that, but because of a coincidence on the stack (the missing parameter
was a NULL, which just so happened to be lying around), the relevant unit
tests actually passed.

The problem with C is that, for all its simplicity, there's a _ton_ of voodoo
which you've got to "just know", and the best practices are not at all clear
from what the language makes easy. In fact, the language makes it easy to make
mistakes and difficult to find them.

I _wish_ Go had made GC optional, I really do.

------
argv_empty
_Guaranteed simple flow_

And then there's setjmp/longjmp.

 _Clear and unambiguous_

Aside from all the undefined and implementation-defined behavior.

 _A macro preprocessor_

Which just does plain, dumb text substitution with no understanding of program
syntax (or the environment where the expanded macro will appear!). CPP's macro
system is a pretty leaky abstraction.

The other points are why I use C (when I use C), but I wouldn't make these
three arguments in favor of C.

------
alexchamberlain
There's an old adage that a computer only does what you tell it to do. What I
love about C? It really does only do what you ask it to; nothing more, nothing
less.

~~~
anonymoushn
When C does what you ask it to do, you're probably just getting lucky. It's
more or less impossible to write a nontrivial C program without relying on
undefined behavior.

~~~
stephencanon
With the exception of the translation limits (a strict reading of which may
allow a compiler that can only compile a single program), it's pretty much
trivial to avoid undefined behavior.

Implementation-defined behavior can be harder to avoid, but that's not a
problem if you're targeting a known implementation.

------
uhhyeahdude
I agree with all of these comments. But... Unless you are an old-school coder
who grew up with C, it is just so much easier to get stuff done with
Python/Ruby or, hell, Bash/Awk/Perl. Granted, that last was for very specific
tasks, but still. Want to write security code? C is is your friend, but you
better be good at it, very good.

~~~
exDM69
> Unless you are an old-school coder who grew up with C, it is just so much
> easier to get stuff done with Python/Ruby or, hell, Bash/Awk/Perl.

True, but who is going to write your Python/Ruby interpreters then? And using
what language?

~~~
shiven
> True, but who is going to write your Python/Ruby interpreters then?

Pythonistas will.

> And using what language?

Using python. Case in point, Pypy.

<\ :P>

~~~
exDM69
> Using python. Case in point, Pypy.

Yes, PyPy is an excellent example of doing low level tasks in a high level
language. It's also quite rare. I think in the future we'll see more examples
of self-hosting dynamic languages that have a JIT-compiler based execution
environment that combines interpretation and compilation.

However, in comparison to the stuff that the PyPy guys are writing, C
programming is easy. And I bet all of the PyPy programmers are excellent C
programmers, because they have to be good with low level stuff anyway.

I still advice learning C programming, and how interpreters and compilers
work.

------
fmkamchatka
One great advantage of C (which was kind of mentioned in the article) is
predictability of the generated code. Compared to a C++ compilers, a C
compiler is much simpler. When you write a for loop, even doing something on a
struct or some fairly "complicated" object, you have a fairly good idea of the
machine code generated. It's also easier to go between the assembly code and
the C code generally. In some applications like email or image processing,
this can be valuable.

~~~
derleth
> predictability of the generated code

To some extent, I hope the code that gets generated _isn't_ predictable in the
way you mean: I _want_ the compiler to know all of the obscure ways to make
string operations go faster by using SIMD hardware, for example. I _want_ that
kind of deep low-level knowledge to be encoded into the optimization passes
because I _don't_ know it and I likely never will. Isn't that why we have
optimization passes to begin with?

------
wmil
What I don't like about C: it's 2012, strings should be easy. Instead they are
a source of bugs and security vulnerabilities.

------
orthecreedence
One thing I LOVE about C is that it's so easy to create APIs that other
languages can use. For instance, if a C library exposes a good API, you can
call it from lisp quite easily with CFFI. This gives you a large advantage:
the low level, raw speed of a C library paired with the high-level forms of
whatever language you choose.

I'm all for people writing programs/apps in C++, but I kind of cringe when I
see a library in C++ because it's a harder language to wrap around.

------
markessien
C is what you use when you should actually be using assembler, but you are not
insane enough to actually do that.

~~~
exDM69
The statement "C is portable assembly" may have been true some time in the
1970's but compilers have improved since then and the statement is no longer
valid.

~~~
derleth
> compilers have improved

And hardware has changed. Remember, the C machine model (the virtual system
you imagine in your head when you write C) doesn't have cache, doesn't have
SIMD, and doesn't have any kind of ability to do things in parallel.

------
gurkendoktor
I think the most dangerous part of C is that many people assume C is perfectly
efficient. It's as if C was the "100%" of performance and other languages are
converging towards it as they get better.

But I don't see how this is true. Pointer aliasing is the biggest example
probably:

[http://www.futurechips.org/tips-for-power-coders/how-to-
tric...](http://www.futurechips.org/tips-for-power-coders/how-to-trick-cc-
compilers-into-generating-terrible-code.html)

And then there is the huge abstraction penalty for things like `qsort()` where
C++ is actually way ahead of C.

------
mccoyst
The preprocessor, and conditional compilation especially, are not something to
love about C. That is probably one of C's most hateful, code-goop enabling
capabilities.

------
cema
C is well placed in that sweet spot close to the hardware where the
abstractions are good enough to hide the hardware specifics from the
programmer and good enough to build more advanced abstractions with sufficient
efficiency.

Because it is so close to the lower levels of abstractions, it ended up a
compact and concise language, easy to keep in mind. This (among other things)
led to C being the quintessential language for some segments of "computer
science": maybe not so much directly but as a reference model.

------
wtf2012a
In embedded product development, C and C++ is King.

------
farinasa
No. ...wait

------
michaelochurch
I've never heard anyone informed bash C. C++ and Java, yes, but not C. Even
people who've never used it tend to know that C has a domain at which (a) it
excels, and (b) it's really the only credible option.

There's actually no such thing as a bad language. I enjoy language wars as
much as anyone else, but languages are only good or bad relative to the type
of problem they're being used for.

For example, what makes C++ and Java odious is that people try to use them for
inappropriate purposes. They aren't platonically "evil" languages, and they
weren't designed by stupid people; they're just inappropriate for over 90
percent of what modern programmers have to do in their professional lives.
When people need high-level features and don't have them, they tend to roll
their own-- badly. This is Greenspun's Tenth Rule and the heart of those god-
awful "design patterns".

C++ and Java, for all that, also have domains in which they're the appropriate
languages to use. They're just very small.

~~~
Jach
Here's your informed person bashing C:
<http://warp.povusers.org/grrr/HateC.html> (Disclaimer: I like C more than
C++, though I can't say I love either of them.)

I do think there are bad languages. Brainfuck is terrible. Maybe there are no
bad _serious_ languages, but you'll have to define what you mean by serious,
and you'll have to argue with Dijkstra's ghost when it comes to COBOL et al.
(though I think he would have liked J). (His two famous quotes against COBOL
come from <http://www.cs.virginia.edu/~evans/cs655/readings/ewd498.html>) I
don't think good/bad is really the best way to judge languages, I'm more
interested in language power, fluidity, and library support.

I'd agree that every language has a _purpose_ , even if the purpose is as
simple as making a joke like in the case of LOLCODE, and that people abuse the
language beyond its intended purpose. I read somewhere someone asserting
"Design patterns are missing language features" and I more-or-less agree with
that.

~~~
Someone
Why would he have liked J? I do not see how he would describe it differently
from "a mistake, carried through past perfection". Also, slightly related: he
may not have seen J, but <http://www.dijkstrascry.com/node/90> shows that he
can not have been totally unfamiliar with APL developments.

~~~
Jach
I hadn't seen that note from him, thanks for the link. I think J solves a lot
of the problems he makes of APL. It can be taught without a J interpreter, it
doesn't require a special keyboard, and it offers abstraction capabilities.
Also it's an answer to some positive things he talks about in this 1985
interview and elsewhere:
[http://www.cs.utexas.edu/users/EWD/misc/vanVlissingenIntervi...](http://www.cs.utexas.edu/users/EWD/misc/vanVlissingenInterview.html)
It supports both functional and imperative styles and it's deeply rooted with
mathematics. It's also "hard" and isn't made for the layman developer. It
encourages a very logical thought-process. I would guess he'd think Haskell
was superior, but I still think he'd at least consider J in higher regards to
APL even if he didn't like it.

------
cheatercheater
> Access to the hardware

Yeah, C is close to the metal. But only on a PDP-11, the assembly language of
which C was conceived to integrate with.

------
jonsen
It's always hard to C a loved one Go.

