
The Unreasonable Effectiveness of C (2013) - nkurz
http://damienkatz.net/2013/01/the_unreasonable_effectiveness_of_c.html?
======
nkurz
Discussed a couple years ago here:
[https://news.ycombinator.com/item?id=5037089](https://news.ycombinator.com/item?id=5037089)

And the followup discussed here:
[https://news.ycombinator.com/item?id=5075370](https://news.ycombinator.com/item?id=5075370)

I repost because I'm becoming more and more frustrated with C, and wondered if
others feel the same. Not because it's too low-level, rather because it seems
to be trying (with limited success) to move to being a higher level language.
There are times when I really do want a "thin layer over assembly", and C
seems to have evolved to a place where that is no longer possible. I explain
my distress more completely in the comments of Yann's article here:
[http://fastcompression.blogspot.com/2014/11/portability-
woes...](http://fastcompression.blogspot.com/2014/11/portability-woes-
endianess-and.html)

~~~
kazinator
If C was ever a thin layer over assembly, it stopped being that sometime in
the 1980's, not recently.

C has not radically changed since the 1989 ANSI C standard. The library is
bigger and there are some bells and whistles in there like designated
initializers, structure literals, complex numbers and (now optional again)
variable-length local arrays.

The trick of abusing C as a higher level assembler that are undefined behavior
today were already undefined behavior already in 1980-something, and before
that there was no standard at all, other than the K&R1 book.

~~~
nkurz
If tracking changes in the specs, you'd be right, but I'm referring more to
the mindset. And I don't mean to imply this is anything sudden --- if pressed,
I'd probably roughly gesture in the direction of 1998-2000, possibly related
to a slow "changing of the guard". In this incredibly long but fantastic
thread, Anton Ertl points to GCC 2.9.5 as the turning point.
[http://compgroups.net/comp.arch/if-it-were-
easy/2993157](http://compgroups.net/comp.arch/if-it-were-easy/2993157) (search
for Ertl). His rhetoric might be excessive, but he makes a good point that in
practical terms, his research on "threaded interpreters" went from being
possible to do in C to impossible.

I'm also not referring to syntax --- I think many of the syntactical
improvements are fantastic and have no downside. And the reliability of modern
compilers is much better, and by-and-large the optimizations produce smaller
and faster code. But what I think we're losing is the transparency of being
able to reason about code execution by looking at source code. It's still the
norm for academic papers to offer source for two approaches to a problem, and
use execution time to prove that one is faster than the other because "it has
more operations" or "it has more memory accesses", without ever looking at the
generated assembling and noticing that one approach has been vectorized and
unrolled, and the other has substituted a completely different algorithm that
drops all the conditionals because the compiler realized they were never being
exercised.

And I don't think it's simply a matter of programmers exploiting undefined
behavior without properly considering the consequences. The inclusion of the
standard library into the spec for the language creates "spooky actions at a
distance" that never existed before, where passing a variable to
"print_debug(a)" allows the compiler to remove the later check for "if (a ==
NULL)" if print_debug() is observed to pass the variable to printf() and if
whole program optimization is being used. Whereas if print_debug() is in a
compiled shared library, this won't happen, and the null-check will work as
intended. I see the reasons compiler writers want this flexibility, but it
sure makes development and debugging much harder than it used to be.

~~~
kazinator
Summary: about a decade ago or so, Ertl ran into some regressions in GCC
uncovered by benchmarking his Forth implementation, logged bugs for them, and
they were fixed.

Some of them were in obscure GCC extensions, like notably computed goto. The
compiler started generating code involving branches to a common instruction
that does the actual indirect jump, instead of just doing that indirect jump.

It's easy to understand how a performance regression affecting such a feature
can slip through, if the behavior is otherwise correct.

It doesn't mean that the GCC sky is falling, as all the trolling in that
newsgroup would have you believe.

~~~
nkurz
I come back to this a day later, after anyone is likely to read it, because
this response continues to bother me. Your response isn't false, but I feel it
really mischaracterizes the issue. These are not trolls in a newsgroup simply
trying to get a rise out of people. They may be wrong, the current
optimization approach may be the best choice available, and GCC may have made
all the correct choices to fulfill its mission as it defines it, but
summarizing as ~"once there bugs and then they were fixed" misses the point.

These are multiple well-respected CS researchers and extremely experienced C
programmers saying they can no longer use C (not just GCC) in the manner they
once did because they believe it's no longer a possible to make the language
work the way they want it to. You appear to be an expert C programmer as well,
and don't agree. Disagreement is fine, but I think you would be wrong to
completely discount what they are saying.

I think it's a matter of what level of optimization you are aiming for. I'm
mostly working on integer compression, and find that I am no longer able to
use C to generate code that maximizes the performance of modern processors.
Ertl's work on threaded dispatch has led to large improvement in the
implementation of modern interpreters
([http://bugs.python.org/issue4753](http://bugs.python.org/issue4753)). As a
tool, C is stronger if it can take advantage of techniques such as this, and
there don't appear to be any other languages higher than assembly where tip-
top performance is possible. I may be just a cranky anonymous troll, but Ertl
should be considered a canary telling us that we are in danger of losing the
ability to make similar optimizations.

------
hbex5
It's basically impossible to write safe code in C. Surely that makes it pretty
damn poor at what it does?

Especially since system code is the place where safety matters most.

~~~
Scramblejams
I have no idea why you're being downvoted. Probably by a bunch of people who
think they can write C and C++ without writing any security bugs. Which,
unless they belong to a vanishingly small group of security experts who write
code in an organization with the same discipline, budget and glacial schedule
of the team writing software for the Space Shuttle, they can't.

~~~
alayne
Memory safety can't guarantee security or correctness. If you guys want to
have a better discussion, you need to be even handed about the complexity of
security. Languages can solve some classes of security problems.

~~~
Scramblejams
Agreed. But memory safety is really such low-hanging fruit right now. Given
that memory bugs still produce massive quantities of severe vulnerabilities,
it seems appropriate to hammer on that aspect of languages.

If memory safety ever becomes a practically solved problem (e.g. somebody's
running an OpenBSD-style count of how many days since a new memory bug popped
up and it gets past, I don't know, hate to be greedy, how about 3?), then I'll
be merrily banging away on the other aspects.

------
vezzy-fnord
Honestly, sometimes I think that the best solution for fixing the security
quagmire we're in would have been not by creating a new system programming
language like Go, Nim, Rust, D or even reviving one of the Wirthian languages
(though having them on the table is very much a good thing), but by creating a
memory safe dialect of ANSI C, and perhaps standardize on a better string
handling library.

In fact, such an effort was started at AT&T back in 2001. The language was
named Cyclone [1]. It met its 1.0 release in 2006. It has since been
abandoned. Which is a damn shame, because it looked like it had real
potential.

Is C a primitive language? Yes. In fact, it's almost stupidly simple compared
to most modern languages. But its greatest weakness also proves to be its
greatest strength. The main cognitive overhead from using C is in its manual
memory management model and certain gotchas in standard libraries. It being
bare bones as it is (but not _too_ much) also makes it surprisingly pleasant
at times. I get the feeling that plenty of modern languages try too hard to be
novel and, for all the freedom you get from not having to worry about anything
below program logic itself, you still end up expending a lot of effort into
complicated high-level patterns that are frequently interspersed with arcane
PL theory.

But that's not even the main reason why something like Cyclone is much needed.
No. It's that we've pretty much perfected a ton of our APIs, like POSIX, to
work with C. It simply feels most natural to work with POSIX in plain C. FFIs
and bindings vary, some of them like Nim's actually feel quite clumsy
(otherwise Nim makes it absolutely trivial to create FFIs, which is great).

Finally, refactoring 30 years worth of code into Cyclone sounds far more
realistic than rewriting the world in Rust.

[1]
[https://en.wikipedia.org/wiki/Cyclone_%28programming_languag...](https://en.wikipedia.org/wiki/Cyclone_%28programming_language%29)

~~~
Araq
Thanks for mentioning Nim! :-)

I can't say I agree with anything you say though... So only memory safety is
C's problem? Not its type system that's very weak in every aspect (not just
memory safety)? Not its missing module system? Not its ambiguous syntax?

You also confuse "simple" with "primitive" and perhaps "familiar". C surely is
primitive, but how is it simple? Simple to use? No. Simple to implement? Not
really. Has a simple mapping to the underlying hardware? That stopped being
true three decades ago.

~~~
lgeek
> Has a simple mapping to the underlying hardware? That stopped being true
> three decades ago.

I've seen this claim repeated a few times in the thread and I still have no
idea what it means.

For medium levels of optimisation it's usually very simple to predict what
assembly code will be generated by C compilers. On many platforms the
operators often match directly to a instruction (e.g. arithmetic and bitwise
operations) or short patterns of instructions (the control flow primitives and
conditional execution, equality testing, function calling, etc). At a higher
level, compiled C functions look pretty much exactly like manually written
assembly language procedures and structs are just blocks of memory with clear
order and offsets. It's also very simple to interface C and assembly code
without any hacks on either side.

------
andrewchambers
C is a great language, for fun I'm slowly working on my own highly C like
langage -
[https://github.com/g-programming/glang](https://github.com/g-programming/glang).

Its basically C with Go like syntax, and a package system instead of headers.
I aim to fully interop with existing C code and have no runtime requirements
beyond what C has.

I'm not trying to go crazy with extra features over what C has though. An
important part of what will make it work, is perfect interop with existing C
code.

Yes I understand memory safety issues, but there is always a need for machine
independent assembly languages. which C essentially is.

~~~
ivoras
Unfortunately, no one will agree exactly on _which_ aspects of C to change and
which to keep - that's why we now have hundreds of languages used by less than
10 people each.

E.g. while I applaud the idea, I found many aspects of your example code
snippets ugly and un-C-like. This is not to say that I'm worthy of judging
your work, but that a) so much of it is a matter of taste rather than
objective thought and b) humans can adapt to literally anything, given time to
get used to it.

~~~
andrewchambers
They are closer to Go than C I admit. Many languages are actually shifting to
grammars similar to this for a few reasons. At the very least the grammar is
less ambiguous, and its easier to code editing tools to recover after parse
errors.

------
byuu
This last bit is so true:

> _I always have it in the back of my head that I want to make a slightly
> better C. Just to clean up some of the rough edges and fix some of the more
> egregious problems._

I'm always mulling over that. "Maybe just namespaces, better macros, function
overloading and member functions (eg this->) would work." Yet I'm sure Bjarne
Stroustrup was thinking the same thing when he started on "C with Classes."
The power to add features must be so overwhelmingly corruptive. So justifiable
in each and every case, in the moment. And then you just can't stop. "Closures
would be helpful. I'd love to write generic containers. Inheritance would save
so much typing.", and the next thing you know, you're working on virtual
inheritance, concepts and user-defined literals. :/

In my opinion, C really does need just a _bit_ more to be great, but it would
need someone with a will of steel to stop and leave things be after that.

~~~
tonysuper
C needs wider adaptation of Apple's "Blocks" extension and MAYBE extremely
limited generics and it's perfect.

~~~
bjz_
> and MAYBE extremely limited generics

C11 has _Generic, but it's pretty much an abomination:
[http://www.robertgamble.net/2012/01/c11-generic-
selections.h...](http://www.robertgamble.net/2012/01/c11-generic-
selections.html)

------
htor
"C has the fastest development interactivity of any mainstream statically
typed language."

This is not true. Using debuggers and crash dumps to reason about your running
program is not fast or interactive at all. It doesn't matter how good the
tools are. They interrupt the workflow.

Working in a REPL on the other hand, is real interaction with your program.
You speak the language to the program and the program responds in the same
language. This is fast.

~~~
sampo
But he said "mainstream statically typed language". Is there one such with a
REPL?

Would Scala be mainstream? OCaml or Haskell probably not.

~~~
htor
Yes, I'd say Haskell and ML are mainstream languages by now.

~~~
angersock
How many companies are basing their businesses on Haskell?

I'm thinking fuckall, but it's always good to know.

~~~
codygman
[https://www.haskell.org/haskellwiki/Haskell_in_industry](https://www.haskell.org/haskellwiki/Haskell_in_industry)

[https://www.fpcomplete.com/business/resources/case-
studies/](https://www.fpcomplete.com/business/resources/case-studies/)

[http://engineering.silk.co/post/31920990633/why-we-use-
haske...](http://engineering.silk.co/post/31920990633/why-we-use-haskell)

[http://bos.github.io/strange-
loop-2011/talk/talk.html#%281%2...](http://bos.github.io/strange-
loop-2011/talk/talk.html#%281%29http://www.shimweasel.com/hs_gbu/)

[http://www.quora.com/What-startups-use-Haskell-for-
productio...](http://www.quora.com/What-startups-use-Haskell-for-production-
work?share=1)

[http://www.quora.com/To-what-extent-do-people-use-Haskell-
at...](http://www.quora.com/To-what-extent-do-people-use-Haskell-at-their-
work-place-How-do-they-use-it?share=1)

[https://angel.co/haskell/jobs](https://angel.co/haskell/jobs)

[http://www.quora.com/What-is-the-largest-commercial-
program-...](http://www.quora.com/What-is-the-largest-commercial-program-
written-in-Haskell)

[http://janrain.com/blog/haskell-janrain/](http://janrain.com/blog/haskell-
janrain/)

[http://functionaljobs.com/](http://functionaljobs.com/)

[http://www.haskellers.com/jobs](http://www.haskellers.com/jobs)

And I've noticed "haskell" at least being listed in job postings more lately:

[http://www.dice.com/job/results?caller=basic&q=haskell&x=all...](http://www.dice.com/job/results?caller=basic&q=haskell&x=all&p=)

------
101914
"You wanted a banana but what you got was a gorilla holding the banana and the
entire jungle."

\- Joe Armstrong

One could argue, easily, this is true for many of the popular garbage
collected languages. It is certainly why I do not care for them. It is also
why I do not care for some of the popular OS's, or most of the popular
"software solutions". It is the unwanted delivery of the kitchen sink when all
I want is a glass of water.

The OP says he's frustrated with C "because it seems to be trying (with
limited success) to move to being a higher level language. There are times
when I really do want a "thin layer over assembly", and C seems to have
evolved to a place where that is no longer possible."

"seems to have evolved"

Some of my favorite programs that continue to work reliably, year after year,
are written in what I guess some would call "primitive," K&R-like C and with
little need for "the" standard libraries. I am not an expert C programmer, but
I have no complaints when reading and editing this "primitive" C. I have seen
others complain about it in forums.

One of my favorite source code comments is in the netcat source where the
author says he's going to write the program as if he's writing in assembly. In
my mind C should be just a thin layer over assembly. Essentially, to me, it
should be a kind of "shorthand" for writing assembly. (That implies the author
should think as if he's writing assembly. And C just takes away the drudgery
of actually typing out all those lines of assembly instructions.) Now, that is
just my opinion. I am not an expert C programmer. I know nothing.

~~~
Kenji
"One could argue, easily, this is true for many of the popular garbage
collected languages [...] It is the unwanted delivery of the kitchen sink when
all I want is a glass of water." Exactly. It's basically like forcing people
to throw all their garbage on the ground and then forcing them to pay for the
garbage men who collect said garbage. It would be easier for everyone to just
go to a bin and dispose of the trash themselves.

~~~
djur
The problem is that there's a great deal of data structures that are difficult
or impossible to write in a provably safe way without garbage collection (or
reference counting). Pick up _Purely Functional Data Structures_ and take a
crack at implementing them in Rust without unsafe{} and you'll see what I
mean.

~~~
belovedeagle
> provably safe

There's the thing.

The reason that some problems can simply be solved more efficiently (on
current hardware architectures) in C than in other languages is that there's a
difference between what is "provably safe" and what is "provably safe to a
compiler". That's the whole point of Rust's unsafe{}; not to write code that's
actually unsafe on purpose, but to say, "this code is safe, even though you
can't prove it" (indeed, perhaps unsafe blocks ought to be renamed to safe
blocks; that would also alleviate the problem of opposite meanings of unsafe
blocks and unsafe functions).

That is to say, it's not true that there are data structures impossible to
write in a provably safe way without automatic GC, since whatever automatic GC
can do the programmer can do too (although, admittedly, at some point one
begins to blur the line between GC and manual freeing, such as with reference
counting). It's just that it's a lot easier for the _compiler_ to prove that
GC-managed code is safe.

I'm not sure that being forced to have the compiler prove that your code is
safe rather than being able to say, "no, I proved it myself with more advanced
techniques" is a good thing. Admittedly, most programs written today in so-
called "safe" languages are probably beyond the scope of their programmers'
abilities to prove safe, but then again, a lot of those programs turn out to
be horribly unsafe even with the compiler's help!

~~~
kibwen

      > perhaps unsafe blocks ought to be renamed to safe blocks
    

We have had long and heated discussions on this topic, actually. My personal
position is that the code inside such a block has fundamental tension: the
compiler must assume that it is safe, while the programmer must in all cases
admit the possibility that it is unsafe. Given that keywords should be
optimized for the reader rather than the compiler, I prefer `unsafe` to
`safe`.

However, that's not to say that there doesn't exist a better word entirely.
Perhaps `unchecked` would suffice...

------
gfodor
So, is Rust a better C? I haven't dug into it too much but that's been my
general impression of how it's been presented.

~~~
femngi
Rust is aiming more to be a better C++. However that doesn't preclude it from
being used in the same space as C and can become impressively lightweight if
you forgo things like the standard library.

I would argue that it is better than C for its safety features alone. I hope
in the future we look back at this decade with its never ending stream of
buffer overflow vulnerabilities with disbelief that we could use something so
insecure for something so vital.

~~~
pjmlp
I have been complaining about it since the MS-DOS days and many of us used
Turbo Pascal, when Assembly wasn't required.

Somehow along the way UNIX spread into the enterprise and brought C along.

------
Elrac
"C has the fastest development interactivity of any mainstream statically
typed language."

I wonder if this statement is true since the invention of Go. A very fast
compile was one of the design goals of Go, and its authors could afford
luxuries (esp. In terms of memory use and object file size) that were
unthinkable in the days of C. For example, IIRC object files contain the
compiled code of their source plus the top hierarchy of modules called.

People have mentioned that changing a .h file in a large C project could
trigger a lengthy recompile. AFAIK, Go minimizes this problem, so if the hype
is correct there should be lots of projects where similar situations will be
handled faster in Go.

My own empirical experience is very limited. I can confirm that Go compiles
much faster than Java for my code, but that will surprise no one and it
doesn't help us compare with C.

Does anybody have more tangible data regarding Go's alleged speed demon nature
esp. as compared to C when compiled with e.g. VS or gcc?

------
arh68
(2013)

First, I think the speed of C relies heavily on the compiler. C is not fast,
not if _I_ wrote the compiler. But GCC is very fast, and ICC at least as much.

I was a little confused by the Erlang wariness, but the reasoning seemed sound

> _At Couchbase we recently spent easily 2+ man /months dealing with a crash
> in the Erlang VM. ... ... it was a race condition bug in core Erlang. We
> only found the problem via code inspection of Erlang._

That does not sound like a fun time, but once the bug is fixed, what's the big
deal? Is there good reason to believe more bugs will come? It wasn't my ass
that got bitten but I'd forgive Linux even if it had a race condition bug. (or
if it crashes touching 1000 files in /etc)

~~~
andrewchambers
No, C is fast, even tcc which does essentially no optimization except for
constant folding is about half as fast as gcc -O1 I think. Basically no
special work is needed to be 50 times as fast as python.

~~~
ris
"No special work" except the massively more laborious effort of writing the
whole thing in C.

~~~
andrewchambers
I was referring to no special work on the part of the compiler writer, not the
application writer.

~~~
jerven
Which python?

~~~
andrewchambers
CPython 2.6 last I tried benchmarking tcc and python. Obviously pypy or pyston
might have an edge for certain snippets after a long jit warmup.

------
blt
C was built as a replacement for assembly programming. It seems low-level
today but it does a huge amount of work for you. Call stack manipulation,
computing offsets for nested struct members, converting arbitrarily complex
conditionals into the right branching instructions, coalescing a sequence of
expressively named intermediate values into the same machine register... these
are the things C does for you. I've never written a serious assembly program
but I can imagine how annoying it is to do all that stuff manually. It would
be easy to screw up.

I think C has been so successful because it made really good decisions about
what to do for you. It eliminated a lot of those busy-work programming tasks
without taking away your fundamental control of the machine. Automatic array
bounds checking, garbage collection, ... they would have been unthinkable for
the original goals of C. The stupid warts are annoying but I think C made
fundamentally sound choices of what to do automatically and what to leave up
to the programmer.

We all talk about modular, abstract code, but back in the day "modular" meant
"use the same calling convention for every int(int, int) function", not
"dependency injection". From that perspective, C must have felt like a huge
leap in modularity and abstraction from assembler.

------
mrcslws
One nitpick:

> _That some of the most heavily used and reliable software in the world is
> built on C is proof that the flaws are overblown, and easy to detect and
> fix._

Easy to detect? Multiple times per year we find out about a security bug in
Linux or Windows that has existed since the 90s.

------
Animats
Some of the unhappiness stems from C++, which was supposed to "fix C".
Instead, it created a big mess. C++ is the only major language to support
hiding ("abstraction") without memory safety. This turned out to be a poor
feature combination, never again repeated. C has neither hiding nor memory
safety, so if it's broken, at least it's visible at the user program level.
Java/Pascal/Modula/Ada/Common LISP/Go/Rust, and the interpretive "scripting
languages", all have both hiding and memory safety. We've at least come to an
agreement on that feature set.

Because of the existence of C++, mainstream C language development more or
less stopped. ANSI C, ISO C, C99, and C11 don't differ by much.

(At one time, I was promoting an approach to make C memory-safe in a way that
allowed mixing safe and unsafe modules to allow a gradual transition and
rewriting of old code. See
([http://animats.com/papers/languages/safearraysforc43.pdf](http://animats.com/papers/languages/safearraysforc43.pdf)).
It's technically feasible but politically hopeless. I'm now pinning my hopes
on Rust and hoping they don't screw up.)

------
yason
The reason I love C——I wouldn't _like to_ love it but I am dragged down back
to C each time so I think I've just given up——is that it costs a bit more to
write.

I used to prototype things with Python by the method of sheer experimentation.
When I found a suitable design, I'd rewrite it "properly" in Python and if
that wasn't fast enough I'd think a bit and rewrite it in C. But that's
happening less and less often these days.

Because C costs a bit more to write it makes me think ahead. And I've (once
again) found that while prototyping in Python is fast it's even faster to
think and then just write C. I write some boilerplate C and start adding the
data structures... this could take a "long" time but once I've figured it out,
writing the actual C code is a breeze. All the mental work has already been
done and once the data structures are right, the implementation just follows.

Curiously, this doesn't exactly happen with Python. Because you _can make a
Python program run_ almost immediately, there's nothing forcing you to the
productive idleness. In C, you'll have to write a bit of code first until you
can get something meaningful up and running: this is the hatching time for
what you really want to write.

I'm not sure why I haven't observed this with other languages. I suppose I
would need to write hefty amounts of Java until I could get a program running
somewhat, but this process of forced productive idleness mostly happens in C.
Maybe it's because there are no layer beneath C and assembly and you
intuitively know the tradeoffs and only a negligible delta of what you write
and what the machine will actually do. Maybe it's because C feels so
_physical_. I don't know. But so far C is the only language that gives me that
process in a native, intuitive way, constantly telling me that "you must not
rush, because you can't rush anyway".

~~~
lmm
Have you ever used a modern strongly typed functional language, e.g. OCaml or
Haskell?

~~~
yason
Yes.

------
aosmith
C is a great language but have you tried go? Feels very c like with a lot of
very nice conveniences.

~~~
jeffreyrogers
Go is garbage collected though, and a lot of people using C don't want a GC'd
language. (It's up for debate whether GC actually matters for most of them,
but that's the feeling nonetheless).

Edit: also, not sure why you were downvoted, since your question at least
deserves a reasonable answer.

~~~
Scramblejams
It's because this place has turned into Reddit. :-(

~~~
Dylan16807
I don't think tossing out the name of a popular alternative really contributes
anything. I especially don't see what's 'reddit' about downvoting such a
comment.

~~~
Scramblejams
His comment was one made in good faith and included a sincere suggestion.
Responses to his comment can educate him, the participants and the lurkers,
which is where the contribution appears. Just because a comment doesn't
instantly add to the conversation doesn't mean that it won't, given the good-
natured participation of others.

Drive-by downvoting is what doesn't contribute anything in this case.

~~~
Dylan16807
The thing is, there wasn't really an insightful question either. Just "Go.
Discuss."

Perhaps if someone actually makes a detailed post on that subject then the
post can be undownvoted. But at the moment there is no contribution, and the
drive-by downvoting sorts it to the bottom, which is a good thing.

~~~
Scramblejams
So you have the knowledge to judge the question uninsightful, but you don't
lend your own insights. And instead of taking the trouble, you're content with
the question being knocked down the page, which reduces the chances of anyone
else doing it. Like I said, very Reddit. Would that we had a community more
interested in illuminating than mercilessly judging.

I'll do it.

@aosmith: It's interesting, because Go's creators explicitly aimed it at the
"systems" niche, which is what C was created to do, but C programmers don't
seem to have picked up the baton the way Pike/etc hoped.

I think it comes down to a handful of things, in no particular order. YMMV, of
course.

(1) Control. C gives you minute control over memory, Go of course does not.
That's very satisfying and useful to many C programmers. Also, it's often
helpful to have a good idea what your code is mapping to in terms of assembly
instructions.

(2) Speed. Go still isn't anywhere near as fast as C in many, many cases.

(3) Portability. Lots of C programmers need (or get satisfaction from) the
ability to compile C on a zillion platforms. Go supports only a few.

(4) Garbage collection. (Sorta a revisiting of point #1). Many C programmers
don't want GC in their code. Now, while I wouldn't mind if my copy of 'less'
used GC, some programmers would. I know I don't want GC freezing my game. So
this is an issue, not one that will ever go away.

(5) Libraries. Go's made strides but can't touch C's library selection. Of
course, you can use C libs from Go, but that has its own complications, and if
the author already prefers C, why pick Go?

(6) Newness. In the context of systems languages, Go is still very new.
Nobody's built an entire userspace out of it, ya know? Not that that's
necessary, but certainly when the Unix programmer sits down and selects C,
s/he knows anything can be built with it. It's long since passed into
respectability. Go's on its way, but isn't there yet.

I'm sure there are a few other things. Don't think there's a way to run a
runtime-less Go. As Damien mentioned, C has a bevy of tools, Go's selection is
much more limited. I'm sure others can think of some more.

~~~
NateDad
Thank you for the insightful response. I think you're mostly correct here,
though there are, of course, subtleties.

Other than C and C++, Go is one of the best languages for controlling memory.
Not freeing, of course, but making it very clear where there are allocations,
where there are copies, exactly how much memory is being used by any
particular data structure.

Portability - you can run binaries created by gccgo in many many places beyond
amd64/x86/arm. No, certainly not as many as C... but probably as many as
anyone would ever want to support. So unless you're targeting a specific
embedded application, then Go is probably fine.

GC is getting a big push in Go and in 6 months they're going to make hard real
time guarantees about the GC... i.e., no more than 10ms pause every 50ms, and
the GC will be hybrid stop-the-world/concurrent, so some memory may be
collected while other code continues to run.

Otherwise, yes, you're right, there are (of course) some limitations to using
Go over C.

However, there are some huge benefits to using Go over C as well... such as
memory safety. There will never be a buffer overflow in your code. Also,
concurrent code will be a thousand times more readable and easier to reason
about.

That's not to say that C isn't the right choice sometimes... I just think the
places where C is the best choice are becoming more and more rare, and not
just due to Go, but Rust as well.

~~~
Dewie
> Other than C and C++, Go is one of the best languages for controlling
> memory. Not freeing, of course, but making it very clear where there are
> allocations, where there are copies, exactly how much memory is being used
> by any particular data structure.

Better than language like Pascal, Ada...?

~~~
NateDad
"modern popular languages that people actually use to write software"?

~~~
Dewie
So you don't know.

~~~
NateDad
It doesn't matter. I'm not going to start a new project at work in either
language. But I might conceivably start one in Python, Ruby, go, JavaScript,
java, Scala, or another well-used language.

------
danenania
What's a good practical way to get my feet wet with C? I want to learn it, but
I'm the sort of person that can only learn a language by actually trying to
build something useful in it. Sometimes it seems like a language that everyone
thinks is important to know, but that no one thinks should actually be used in
a real world project unless you're working on embedded systems or building an
OS. What are some ideal (and beginner-friendly) use cases?

~~~
angersock
Go download SDL 2.0 and build a simple breakout game, or space invaders, or
something. Add networking support.

You won't get to hide from the annoying stuff in C (memory allocation, string
manipulation, etc.), but the problem space (a simple game) is right there.
It's also something that many, _many_ people have done before, so it'll be
easy to start.

~~~
danenania
Thanks, I really like the simple game idea, and SDL looks like a cool
framework. Also neat that it can compile to ios/android-compatible binary
(though perhaps that would introduce a new can of worms).

------
maaaats
It claims C has the fastest build/run cycle. Is this true? Many non-compiled
languages I can redefine my functions at runtime, and with Java I can hotswap.

~~~
zik
Go has the fastest build/run cycle I've seen. You can usually compile compile
to a binary and run it quicker than it takes a python runtime to start up.
It's totally viable to use Go as a scripting language while compiling to
binaries from source.

~~~
Scramblejams
I mostly work in Python but I had a similar scripting-like experience during
my Go project -- with a small codebase, the time it spent compiling was barely
perceivable, if at all. Very impressive, and shows you what's possible.

Semi-relatedly, the downvoting around here has gotten completely out of
control. It's sad, what's happened to HN.

------
SCdF
There is currently a really cool project I suggest (if you're interested in
learning / seeing C in action) called Handmade Hero[1].

He[2] is making a game, from scratch, in (mostly) C (but with a little bit of
C++ niceties thrown in), and streaming[3] the entire process for an hourish,
Monday -> Friday. It's intended to be a tutorial in both learning C and
learning from-scratch game development (where from scratch means using GDI and
like, parsing your own wav files).

It's really cool to watch, he's an entertaining guy, afaict is a pretty decent
teacher (I know zero C, but C-style languages, and I _think_ I'm keeping up),
so I recommend checking it out.

[1] [http://handmadehero.org/](http://handmadehero.org/) [2]
[https://twitter.com/cmuratori](https://twitter.com/cmuratori) [3]
[http://www.twitch.tv/handmade_hero](http://www.twitch.tv/handmade_hero)

~~~
benwaffle
unfortunately, he uses windows he said he will show how to do this on linux
later

~~~
zellyn
Check out
[http://davidgow.net/handmadepenguin/default.html](http://davidgow.net/handmadepenguin/default.html)

------
Aldo_MX
Every time I see someone praising C I curse Microsoft for not having proper
support for C99 in Visual Studio.

~~~
AlexeyBrin
Visual Studio 2013 has better support for C99, here is an article from MSDN
about it
[http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-librar...](http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-library-
support-in-visual-studio-2013.aspx) . But it is not a complete C99
implementation.

The good news is that with VS 2015 you will be able to use Clang for compiling
C code, so hopefully a complete C99/C11 implementation on Windows at some
point.

~~~
pjmlp
Microsoft reiterated at Connect 2014 that only the parts required by the C++
standard are to be included, as well as, smaller parts required by well known
FOSS projects that they see value in supporting on Windows.

Clang support is only planned as compile target for Android and eventually
iOS.

Check going native videos from Connect.

~~~
AlexeyBrin
> Clang support is only planned as compile target for Android and eventually
> iOS.

I know they plan to officially support only Android and iOS. However, even
today I can use Clang to create Windows executables from the command line.
Once the support for Clang will be included in VS, it is only a question of
time until someone will swap the Clang from the Android NDK with a Clang
compiled for Windows.

------
lordnacho
The boring response would be that different languages have different
strengths. C is indeed capable of being very fast, mainly by virtue of letting
the dev have fine control over memory. But execution speed isn't the only
metric. Sometimes you just need something to be done quickly and you know you
aren't going to hit the constraints (time, space) of the system, so you might
as well go with something like .NET to reduce your development time.

The point about the tooling I'm not so sure about. There's a lot of languages
out there with well developed tools. And the tools tend to address the pain
points: you have GC profiling in .NET, and you have Valgrind-type tools in
c++.

------
bkeroack
"I always have it in the back of my head that I want to make a slightly better
C. Just to clean up some of the rough edges and fix some of the more egregious
problems."

This is called Go. Brought to you by the same people who gave you C.

~~~
imanaccount247
No it is not. Go is only "like C" in the sense of the most superficial
syntactic similarities and that it is primitive. It isn't even in the same
world as C, it is just another high level garbage collected language that
compares poorly with the rest of the languages in that group. Go was not
brought to us by the people who made C. It was brought to us by Rob Pike and
Russ Cox. Dennis Ritchie gave us C.

~~~
jbergens
Ken Thomson was (and is) also involved with creating Go and he was also one of
the writers of Unix. He actually invented the B language which preceeded C, so
it was close :-) I think he wrote a lot of C in Unix and was therefore part of
making C popular.

~~~
imanaccount247
Ken had nearly as little involvement in Go as he had in C, they just asked him
stuff. Did he write any of it at all? "From the same people as C" is a factual
claim, and it is factually incorrect. Ken absolutely did not bring us C, and
it is very sketchy to claim he brought us go. Go is brought to us by the guy
who came to bell labs after it was all over and decided to try to pass himself
off as "the bell labs guy!" for the rest of eternity.

~~~
myg204
Just putting this from the official FAQ, for the record.

    
    
        Robert Griesemer, Rob Pike and Ken Thompson started
        sketching the goals for a new language on the white board
        on September 21, 2007. Within a few days the goals had
        settled into a plan to do something and a fair idea of what
        it would be. Design continued part-time in parallel with
        unrelated work. By January 2008, Ken had started work on a
        compiler with which to explore ideas; it generated C code
        as its output. By mid-year the language had become a
        full-time project and had settled enough to attempt a
        production compiler.

~~~
imanaccount247
Yeah, that's deliberately selling Ken's involvement as hard as you can without
dishonesty, and it still shows he wasn't actually involved in go, just
"exploring ideas for a language".

------
TwoBit
C is not the fastest language. C++ is faster than C. For example, the only way
you can hope to match C++ inline template algorithms in C is with a horrific
macro scheme.

~~~
sharpneli
[http://benchmarksgame.alioth.debian.org/u64q/c.php](http://benchmarksgame.alioth.debian.org/u64q/c.php)

Gives the indication that C++ is faster in practice only when your algorithms
are so complex that writing them in C starts to become tedious.

And frankly C++ can never match C until they introduce restrict. Only with C99
C was able to match Fortran. C++ does not have that luxury yet.

~~~
TwoBit
What you say about restrict is hard to consider because every C++ compiler
supports restrict.

Also, I frequently see those types of algorithms that benefit C++. It's not
just an STL thing.

~~~
sharpneli
Yeah it's true that restrict is well supported, mostly because all C++
compilers are also C compilers.

Maybe the biggest reason why C++ is slower in practice is because the
programmers tend to feel that using features unique to C++ almost mandatory.
Even though technically the pure C program also compiles fine in C++.

------
plow
It’s as if people make asymptotic progress towards the goal of the ‘ultimate
programming language’, the newer innovations which may well have improvements
are too marginal to be beneficial, there is too much existing inertia, that is
why the more prominent modern ones incorporate interoperability with C often.
It would seem more sensible to say as the author of this post seems to
propose, that C is the de facto ultimate.

------
facorreia
> C is the fastest language out there.

I thought it was Fortran.

~~~
codygman
Fortran is fastest for matrix manipulation and other maths stuff IIRC.

------
fithisux
In this thread I saw no mention of Freebasic. It has some good features and is
comparable to C. TerraLang is another interesting approach (for system
programming languages).

But the fundamental flaw is that in many cases a DSl that compiles to
something lower level is the way to Go.

------
dothebart
one of the best things C has to offer was omitted herein - the preprocessor
;-)

------
neutronicus
Hmmm. I work on a pretty large scientific computing project written in C++.
Complex numbers in C++ are much, much better than they are in C. In general,
I'm very happy it isn't in C.

~~~
panzi
Are you comparing C's built in complex type with a C++ library or a C++
library with a C library?

~~~
neutronicus
In both cases it's libraries defined by their respective standards, I think.

The important thing is that the C++ class overloads operators and mathematical
functions, and the C class doesn't.

~~~
panzi
C99 has a builtin complex type. "double complex" (similar to "unsigned int").
Of course all arithmetic operators are defined for that type.

Example: [http://coliru.stacked-
crooked.com/view?id=0d295064bd367eca](http://coliru.stacked-
crooked.com/view?id=0d295064bd367eca)

Source:
[http://en.cppreference.com/w/c/numeric/complex](http://en.cppreference.com/w/c/numeric/complex)

Have you tried that? Of course Microsoft refuses to implement C99, so you
could only try it on non-Microsoft C implementations.

------
otikik
Remember that where there's C, there can be Lua.

Just saying.

------
demarq
call us when the honeymoon is over.

------
imanaccount247
>Every time there is a claim of "near C" performance from a higher level
language like Java or Haskell, it becomes a sick joke when you see the
details. They have to do awkward backflips of syntax, use special knowledge of
"smart" compilers and VM internals to get that performance, to the point that
the simple expressive nature of the language is lost to strange optimizations
that are version specific, and usually only stand up in micro-benchmarks.

I see this kind of statement a lot, and it simply does not hold up to even a
cursory look. Where are the awkward backflips of syntax, special compiler or
VM knowledge, or version specific optimizations here?

[http://benchmarksgame.alioth.debian.org/u32/benchmark.php?te...](http://benchmarksgame.alioth.debian.org/u32/benchmark.php?test=mandelbrot&lang=java&lang2=gcc&data=u32)

[http://benchmarksgame.alioth.debian.org/u32/benchmark.php?te...](http://benchmarksgame.alioth.debian.org/u32/benchmark.php?test=fasta&lang=java&lang2=gcc&data=u32)

Why are there so many java web frameworks/libraries/servers that offer
performance close to C?

[http://www.techempower.com/benchmarks/#section=data-r9](http://www.techempower.com/benchmarks/#section=data-r9)

>Critically important to developer efficiency and productivity is the "build,
run, debug" cycle.

This is a pretty bizarre claim. Sure, having an equally archaic and primitive
process but 10 times slower is obviously worse (C++), but that doesn't mean
having an archaic and primitive process is good if it is fast. I rarely ever
run my code, much less debug it. Freeing myself from that horrible way of
working was one of the greatest things about working in a language with a
useful type system.

~~~
panzi
The benchmarks you linked are interesting. Rust is #1, right before C:
[http://benchmarksgame.alioth.debian.org/u32/performance.php?...](http://benchmarksgame.alioth.debian.org/u32/performance.php?test=mandelbrot)
Maybe Rust will finally be a real competitor to C.

~~~
detrino
While Rust is indeed competitive with C here, its likely only number #1
because LLVM is generating better code than gcc for this example. I'd expect
clang/C to run at least as fast.

~~~
igouy
And see x64

[http://benchmarksgame.alioth.debian.org/u64/performance.php?...](http://benchmarksgame.alioth.debian.org/u64/performance.php?test=mandelbrot)

------
adamnemecek
"When someone says: 'I want a programming language in which I need only say
what I wish done', give him a lollipop."

What a shitty, shitty quote.

~~~
Double_Cast
This quote confused me. What does it mean?

~~~
ArtB
That dream is so child-like that you should treat that person as a child.

------
rubiquity
It almost seems cruel to have a blog post written by someone from more than a
month ago on the top of HN on Thanksgiving Day. I can picture the turkey and
stuffing slowly tumbling out of Damien's mouth as he learns a blog post he
wrote from early 2013 is at the top of HN right now.

