
The cost of forsaking C - Halienja
https://medium.com/bradfield-cs/the-cost-of-forsaking-c-113986438784
======
Nursie
Ah, C, the love of my life...

Want minimal syntactic sugar and a language that's not prone to feature-of-
the-week hipsterism? C

Want to make tiny binaries for some obscure system with virtually no storage
or RAM? C.

Want to know where every last cycle goes and explicitly control everything? C

Want to trivially import any of the huge array of existing libraries? You
guessed it...

Want to do something you really shouldn't, and any 'sensible' language might
attempt to stop, but is called for right here and now...

It's not the safest language, it's not the most expressive, but the syntax is
small enough to hold in your head and the body of existing, available work is
HUGE. I've been working in C for 15 years and, while I enjoy forays into other
languages, it will always be my love.

~~~
atilaneves
> Want to make tiny binaries for some obscure system with virtually no storage
> or RAM?

C++, D, Rust, ...

> Want to trivially import any of the huge array of existing libraries? You
> guessed it...

If C can talk to it, so can anything else. Granted, having the preprocessor
means no bindings, but C++ has that too.

> Want to do something you really shouldn't, and any 'sensible' language might
> attempt to stop, but is called for right here and now...

C++, D.

Want undefined behaviour? C. Want segfaults? C. Want memory leaks? C. Want
memory corruption? C. Want to write insecure code? C. Want to write your own
containers? C. Want Go's approach to generics? C. Want to spend 3x as much
time writing code as a comparable C++ solution (not to mention more productive
languages)? C.

I've known C for 21 years now. I just quit a job as a C programmer for
embedded systems. If I can help it, never again.

~~~
StavrosK
> Want to spend 3x as much time writing code as a comparable C++ solution

Coming from Python and dabbling in C for embedded software, this is the one
that gets me the most. It's so frustrating to be spending hours doing
something you can do with one line of the regex library in Python...

~~~
jackhack
I don't understand your complaint. There are mature regex libraries for C
found with the obvious Google search. Source code included. Why would you not
just pick and consume one, as you would in Python?

Overall though I think what you may be seeing is simply the stratification of
software development; what began in the 70s and 80s has come to fruition.
There are different planes of existence, like thermoclines in the oceans. A
developer may (and is likely to) live in one forever, without crossing above
or below. Each has its purpose. While I wrote my own database and rendering
engines in the 80s as part of applications development, I wouldn't dream of it
today unless there was a very, very good reason. Same goes for network stacks.
Or math libraries. Memory managers. Etc.

Sure, coming from the Python ecosystem, you will feel as though there is a
shortage of auto-pilot-like assistance, but you must realize you are in a very
different world now - Embedded work is (frequently) focused on predictability,
responsiveness, efficiency, and even moreso with realtime work. You are the
engineer in charge, and all the safe boundaries and cushions of the
interpreted language world are now missing. Want to REALLY feel naked? Drop
down to assembly on any platform and try to emit a simple "hello world." For
those who have never done so, it's a humbling experience but rewarding.

Remember that C was designed as a "universal assembly language", easily
portable to different architectures and close (enough) to the metal so the
programmer can have full control over the machine. Best analogy I've heard: C
is like a chainsaw - used carelessly one can cause enormous damage and
destruction, but in the hands of a skilled/experienced craftsman, very clever
solutions are possible.

~~~
StavrosK
> I don't understand your complaint. There are mature regex libraries for C
> found with the obvious Google search. Source code included. Why would you
> not just pick and consume one, as you would in Python?

Mostly because I'm used to one single place for libraries (PyPI) and I don't
know how to find (and evaluate) libraries in C. I also don't know if they'll
run on my MCU or how much RAM they require. I have found one or two embedded
regex libraries, but they were very limited in what they could do or failed
some other criterion.

Besides, that was just an example, it's just death by a thousand cuts with
similar things one after the other.

~~~
kkarakk
-I don't know how to find (and evaluate) libraries in C

you can replace C with any language. you're evangelising about the toolbox you
know instead of learning about the hammer you are familiar with and don't want
to learn how to operate

~~~
StavrosK
Alright, I'm game. Where's the C library repository, and what's the manager I
can use to handle dependencies automatically?

------
noelwelsh
I agree John Regher's take on teaching C:
[http://blog.regehr.org/archives/1393](http://blog.regehr.org/archives/1393)
In summary, it's a useful skill to have but you're not doing your duty as an
instructor if you don't make your students aware of its many shortcomings.

I particularly want to take issue with the claim in the original post that "C
helps you think like a computer". C's machine model might have been a good
model for the machines at the time at which it was developed, but it hasn't
been an accurate model for a long time. A simple example is C's assumption
that memory is flat and all locations have an address. With multiple layers of
caching and nearly a couple hundred registers in current CPUs this is far from
the truth. If you think programming in C is programming at the machine level
you are deluding yourself.

~~~
bluetomcat
> With multiple layers of caching and nearly a couple hundred registers in
> current CPUs this is far from the truth.

Add to that the aggressive optimisations performed by modern compilers and
that mental model breaks completely. It may be a good conceptual model, but
it's not the model under which your program actually executes.

However, even programming in assembly keeps you very "far from the truth",
since modern CPUs are very complex beasts internally and that complexity is
mostly not visible in the ISA.

~~~
sigjuice
Yup. Caches, prefetching, NUMA, out-of-order execution, speculative execution
etc.

~~~
planteen
The thing about speculative execution and out of order execution to remember
is that you always get the expected result from a single threaded perspective.
If you throw in interrupts or threads, you know you must tread cautiously in
C.

Few things have made me more nervous in my career than seeing a ISR making use
of C++ standard library features. When I asked the engineer how they were sure
this was safe and worked under the covers, I was immediately dismissed as "the
compiler takes care of all that." The project only ever worked at -O0 and was
still buggy. The engineer blamed the hardware.

~~~
claudius
> The thing about speculative execution and out of order execution to remember
> is that you always get the expected result from a single threaded
> perspective.

Could you elaborate on this? I thought at least speculative execution was
handled internally in the CPU and essentially not visible to the user apart
from the performance impact?

I’m not sure what you refer to as out-of-order execution, is this execution
reordering within the C compiler?

> If you throw in interrupts or threads, you know you must tread cautiously in
> C.

Naturally, yes.

------
rvense
It's hard to over-estimate the historical importance of C, and the amount of
groundbreaking work and important knowledge codified in C codebases.

Also, it can't be denied that there will always be areas where the exact
control of memory layout that C gives you is not just nice-to-have for
performance reasons, but a prerequisite for a good implementation or
understanding of some algorithm.

Neither of those points, however, mean that C is the only suitable language
imaginable for doing low-level work, or that the past forty years of
programming language research are irrelevant to the spaces that C excels in. I
think Rust shows quite succintly the immense value of the combination of an
expressive type system and C-like zero-overhead abstractions.

Learning C, like learning some assembly languages, to some extent is probably
necessary if you're serious about understanding computers, just to understand
what's going on. But when it comes to actual use in production systems, I am
glad that we are seeing serious alternatives to a language so prone to simple
bugs as C. Think of all the time and money that have been lost to buffer
overflows and segmentation faults.

~~~
S_I
As much as the Rust community does right with respect to the technical aspects
of the language, as much they still don't (seem) to understand the non
technical problems it has.

Do you know which non technical advantage C has? Multiple implementations.
Don't like gcc, use clang. The Keil compiler has a certain bug that screws
your project? Use IAR. And so on.

That is one thing. Another thing (at least at the company i work for and the
ones i know) is, companies that write code for infrastructure or machines that
need to rung a looong time won't ever trust a language (and toolchain) that
comes in versions and not in IEEE standards. That may or not be stupid, but it
is the reality i've seen so far.

P.S.: Before someone says C only NOW has multiple implementations, yes, at
some point in time that was true, but i was VERY easy for compiler vendors to
implement a C compiler (speak ROI). Time will tell if this will be true for
Rust as well.

~~~
Manishearth
> companies that write code for infrastructure or machines that need to rung a
> looong time won't ever trust a language (and toolchain) that comes in
> versions and not in IEEE standards

The Rust team has a very high commitment to stability, and does way more to
maintain stability than any other language/compiler I know of (by testing new
versions and potentially-breaking-changes against the entire ecosystem)

> still don't (seem) to understand the non technical problems it has.

Just because multiple implementations of Rust don't exist (there are a couple
but nothing 100% feature complete iirc) doesn't mean that the community
doesn't understand the need for it. Alternate implementations are hard to
write and take time. The language is still new, but work is being done towards
speccing it (e.g. the unsafe code semantics work being done right now). Note
that most languages have gone for years without getting a proper spec or
alternate implementations. This is an advantage C has over Rust, agreed. It's
usually not a dealbreaker, though.

~~~
S_I
>The Rust team has a very high commitment to stability, and does way more to
maintain stability than any other language/compiler I know of (by testing new
versions and potentially-breaking-changes against the entire ecosystem)

Yes, but my experience is that they don't seem to manage generating the kind
of trust needed to get my peers to give it a serious go. It's a purely social
and subjective problem.

>Just because multiple implementations of Rust don't exist (there are a couple
but nothing 100% feature complete iirc) doesn't mean that the community
doesn't understand the need for it.

As i said, it SEEMS to be so. That means that it is a subjective impression my
colleagues and me get. It is the job of the community to generate trust, not
the (potential) user's.

>Alternate implementations are hard to write and take time.

Yes, see my P.S. Time will tell if it's worth it to compiler vendors. C made
it easy for them right from the start.

>Note that most languages have gone for years without getting a proper spec or
alternate implementations. This is an advantage C has over Rust, agreed. It's
usually not a dealbreaker, though.

Not a dealbreaker for whom? In the infrastructure and big machine business you
will see C, some C++ and Ada. All standardized.

If the Rust community wants to offer an alternative for C, C++ and Ada, AND
want Rust to succeed as an alternative, they need to understand that trust (in
the toolchain) is generated in different ways in different industries.

~~~
nickpsecurity
Not a dealbreaker for whom? In the infrastructure and big machine business you
will see C, some C++ and Ada. All standardized.

What are you talking about? There was a C standard because so many groups
picked up C. The Ada mandate actually reduced its uptake with a bit of a
rebound latter on when the tech itself was better (esp compilers). C++ got
uptake before a standard plus fed into the C standard. So, no, the lack of a
standard isn't stopping adoption by industry outside select firms that won't
pick up tech unless it has a standards document which often isn't even
accurate.

What industry does care about are compilers, IDE's, existing libraries,
available talent, ecosystem, who they can pay for support. These things aren't
at a level they like yet. Adoption stays low.

Note: Most infrastructure is written in C due to talent and compiler
availability more than anything. That's what most embedded people tell me.

~~~
S_I
That was then, now is now. Today, at least in europe, big companies do care
about standards. Go ahead, try proposing using a Compiler that does not
implement any standard like C,C++ or Ada in the Automotive industry.

As for the rest, i agree.

~~~
nickpsecurity
Safety-critical industries here and over there are regulated by standards.
They're an exception. Average, embedded system can use whatever it wants so
long as it produces code to run on target board. Making your tooling generate
C as output is easiest way to cheat. It's what I did with my BASIC 4GL. People
were none the wiser.

------
dreta
There’s a lot of problems with C, like the fact you have to break out of case
statements, or string concatenation, or overuse of the static keyword. These
are actual problems, which C++ doesn’t even begin to try and solve, instead
introducing useless features and bloat. C is still one of the few popular
languages that allows you to talk to the machine directly. It’s a language
that doesn’t rely on hidden run-time logic, or hidden implementation costs. It
doesn’t enforce any particular programming style on you, and lets you do
anything a process is capable of doing.

Software engineers these days are so lost in abstractions and design patterns
that they forget that at the end of the day a program is just data, and a set
of operations that transform that data. There’s huge value in writing code
that does everything explicitly from top to bottom, both from a readability,
and from a debugability standpoint. Instead, these days, software is designed
using UML diagrams and OOP concepts while pretending that objects are ideas
that float in some abstract disconnected space. All in the name of concepts
envisioned by people who write books instead of programming, and who never saw
even a glimpse of a problem you’re trying to solve.

Languages like C will never become obsolete. There’s always a new frontier of
hardware that needs fast, tailored software. Few years ago that was phones,
and watches, next it might be tiny implants. Anybody who thinks languages like
C is obsolete should ask themselves “why was my Comodore64 more responsive
than a PC i bought in 2016?”, or "why is my dual-core Android smartphone with
1GB of RAM barely usable after a year”. Modern languages and programming
practices have this amazing ability to completely negate the massive progress
hardware has made.

~~~
Avshalom
>>Few years ago that was phones,

ObjC and Java

>>Anybody who thinks languages like C is obsolete should ask themselves “why
was my Comodore64

Assembly and Basic.

~~~
mikejmoffitt
Surely Basic is not responsible for the Commodore being responsive. Java was a
total dog on phones for a long time, too.

~~~
Avshalom
Well C wasn't responsible for the Commodore either. And whether Java was a dog
or not, thats what people went with, from your SIM card to JavaME snake games
to Dalvik/ART. People looked at these resource constrained environments and
went "yeah lets use Java".

ETA: it's probably worth put scare quotes around "resource constrained" when
talking about Android and IOS but phones were dreta's example.

~~~
marrs
and promptly went out of business when the iPhone showed up

~~~
Avshalom
a phone that launched full of ObjC and Javascript with a SIM card running
Java...

~~~
marrs
ObjC is a native language and a direct descendent of C, and powered the
phone's built-in apps. JS was provided for 3rd party developers, who
incidentally rejected it. I wasn't aware of the SIM card running Java. I guess
Java was good enough for that job since I never noticed any performance issues
with the iPhone, unlike my Palm Pre which was plagued with them, and had a
terrible battery life.

------
Animats
The industry took a giant step backwards when C displaced Pascal. The original
Macintosh apps were in Pascal and the MacOS API were all Pascal-oriented.

C has three fundamental issues:

1) How big is it?

2) Who owns it?

3) Who locks it?

C's lack of help in dealing with all three is the main cause of most memory-
related program bugs. I once tried to fix #1 in a backwards compatible way.
See [1]. After much discussion on some mailing lists, there was general
agreement that this was technically feasible but not politically feasible.

(I once had hope that Rust would replace C, but Rust has gotten too fancy,
with too much input from the functional programming people, the template
enthusiasts, and the type theorists. Rust isn't bad, but it's at least as
complex as C++.)

[1]
[http://www.animats.com/papers/languages/safearraysforc43.pdf](http://www.animats.com/papers/languages/safearraysforc43.pdf)

~~~
kibwen

      > it's at least as complex as C++
    

You repeat this phrase like a broken record, but have yet to back it up every
time that I have asked why you have this opinion. C++ is an order of magnitude
more complex than Rust.

~~~
Animats
\- You need templates to do anything, because the standard library uses them
so heavily. They're rather opaque.

\- The functional control flow style, where everything involves closures, is
much harder to understand than imperative control structures.

~~~
Manishearth
Generics, not templates.

They're not opaque. Templates are more opaque because of the lack of self
documenting bounds, perhaps (i still wouldn't call them opaque, just more so
than Rust generics)

This is the millionth time you're repeating that garbage about imperative
control flow. It boils down to a use of closures in a few stdlib functions.
We've had this argument before, the essence of your point is that it is
_different_ from C. Of course there is a learning curve but that is there the
other way too. Once you get used to it the control flow is pretty
straightforward. And in most cases you can avoid the closures and write your
if or loop manually.

~~~
Animats
Rust's control flow primitives are coming to be defined by libraries, not the
language, and tend to grow over time. For a long time, we've been able to get
by with a small, well-understood set of control flow primitives, those defined
by Wirth many years ago. Now we have this in Rust:

Type Option. The 2014 version.[1] The 2016 version.[2]

(Coming soon, the "?" operator.[3])

Here's an example of excessive cleverness [4]:

    
    
        fn main () {
            let number: f64 = 20.;
            // Perform a pipeline of options.
            let result = Some(number)
            .map(inverse) 
            .map(double)
            .map(inverse)
            .and_then(log) 
            .map(square)
            .and_then(sqrt);
            // Extract the result.
            match result {
                Some(x) => println!("Result was {}.", x),
                None    => println!("This failed.")
           }
        }
    

(It's surprising that you can use .map on a singleton. Does this actually
generate collections of one element and discard them, or what?)

The designers of Go knew when to stop. The designers of Rust don't.

[1]
[https://web.archive.org/web/20140814230239/http://doc.rust-l...](https://web.archive.org/web/20140814230239/http://doc.rust-
lang.org/std/option/type.Option.html)

[2] [https://doc.rust-lang.org/std/option/enum.Option.html](https://doc.rust-
lang.org/std/option/enum.Option.html)

[3] [https://github.com/rust-lang/rust/issues/31436](https://github.com/rust-
lang/rust/issues/31436)

[4] [https://hoverbear.org/2014/08/12/option-monads-in-
rust/](https://hoverbear.org/2014/08/12/option-monads-in-rust/)

~~~
Manishearth
You're redefining "control flow primitive". Those are not primitives, and they
affect control flow as much as functions do, aside from `?`. Closures are a
concept that C doesn't have, but once you get them they obfuscate nothing.
These library calls obfuscate control flow only as much as regular function
calls would.

Nor are you forced to use code like the excessively clever version you talk
of. People who are used to monadic programming have the _choice_ to.

You're making the same crappy arguments like a broken record. I'm not having
the same tired old discussion again.

------
delegate
The author uses C and C++ interchangeably, but these are two distinct
languages.

Although technically a superset of C, C++ has constructs and paradigms which
make you think in totally different ways.

In fact C++ introduces many language features which (should) protect
programmers from 'C' mistakes in their C++ code.

For example, in modern C++ you shouldn't manage memory directly, but use smart
pointers and containers. You can, but you shouldn't.

And there are dozens of such recommendations. Which is the right approach,
imho. You can still do the low-level dangerous stuff if you feel brave, but
officially you should stick to the 'safe' paradigms that the language now
offers.

However, the paradigms that C enforces on you are the paradigms of how to do
things _fast_. You wear no protection so you are much more nimble, but much
more vulnerable at the same time. Which is good for some types of projects,
but not for all.

~~~
palunon
C++ is not even technically a superset of C...

`auto` has very different meanings in both languages, and you can't omit the
return type of an int-returning function in C++

~~~
david-given
Have you ever tried to compile an old C program which extensively used
variables called 'old' and 'new' with a C++ compiler? I have.

Also, C++ doesn't allow implicit casts from void* to any pointer type, which
is a common C idiom.

------
MrBuddyCasino
> C helps you think like a computer

I recently bought K&R, doing a bit of micro-controller stuff without the
Arduino abstractions, and this I can agree with. I now have an idea how code
really gets executed on a CPU, and how the contract between the bare metal and
the assembler code for doing so looks like.

That the concept of a stack is built into x86, and why calling conventions are
important, all of this stuff I had no idea doing Java development for all
these years. What do I need a linker for? Object files, what?

I don't really like it, but there is something strangely beautiful about it -
if you look hard enough, you can see the machine shining through the
unforgiving cold blue ice that is C.

~~~
leppr
_> calling conventions are important_

Curious what you mean by that, in what way learning C made you understand this
better than Java or any other language did?

~~~
MrBuddyCasino
As mentioned, I don't particularly like C, so I've explored Rust a bit. I
tried to expose a Rust function to C, heres the signature:

    
    
      #[no_mangle]
      pub extern "C" fn count_substrings(value: *const c_char, substr: *const c_char) -> i32
    

So I came at it from the opposite direction, and once you go down the rabbit
hole of what "no_mangle" and "extern C" does, thats where it leads you.

Along the way you inevitably pick up topics like alignment and struct packing.

------
Manishearth
TLDR: Goto last line of this comment

> It is still one of the most commonly used languages outside of the Bay Area
> web/mobile startup echo chamber;

Fair.

> C’s influence can be seen in many modern languages;

Saying that that's a reason to learn C is a non sequitur. Why?

> C helps you think like a computer; and,

So does C++. And Rust. And D. All the stuff about databases can be done in any
of these languages, C doesn't have a monopoly over letting you be close to the
metal. It's one of the only languages that pretty much _forces_ you to be
close to the metal, but that's not a plus point.

> Most tools for writing software are written in C (or C++)

True. Hacking on your tools is great. But hacking on your tools rarely
requires proficiency in a language (unless you're doing something major, which
you're not), I've hacked on tools written in all kinds of languages that I
don't know.

And the justification behind this point follows the same flimsy reasoning as
the previous one, the reasoning that C is the only low level language out
there. The post gives "browsers, operating systems and languages" as examples,
but all three of these exist in Rust (Servo, redox/intermezzos/a bunch more,
and rustc). I'm sure that D is up to the task for such software too, if it
doesn't have them already. C++ of course has all of these.

Sure, you need to know _some_ C when doing low level programming and/or FFI.
But nobody's arguing against that. "Everyone “has been meaning to” learn Rust
or Go or Clojure over a weekend, not C." is a false dichotomy. With Rust for
example it's pretty easy to learn enough C to manage once you've learned Rust
(there are tons of folks in the Rust community who have done this). You're not
_forsaking_ C, you're just focusing on something better. You can learn enough
C to be able to read code and do FFI, and you're pretty much set for writing
databases or operating systems or networking stacks or whatever. Reading C
isn't too hard and if you speak another low level programming language you can
pick this up over a weekend.

The only valid argument I see here is that C is is still _used_ a lot in
existing codebases, and you should be proficient if you want to be able to
contribute significantly to them. Of course. But cut all the crap about C
being the _only_ language that can handle these use cases.

~~~
kibwen

      > The post gives "browsers, operating systems and 
      > languages" as examples
    

Actually, I can't think of any browsers that are written in C. Unless, wait,
does Lynx count? :)

~~~
harry8
netscape was when it was popular, then they re-wrote in c++ (when compilers
for that language were much worse than they are now) and everything went to
crap. Templates work now and are pretty much consistent accross platforms,
they didn't then or so says JWZ, wasn't there to confirm it but seems very
plausible based on what experience I had of visual c++ 6 at the time

------
kensai
Although there is little need for C to evolve (apart from certain security
holes), I think there is space. Thankfully, there are still persons that care
about its evolution.

The K&R is a classic, but it shows its age, especially as we have reached C11
by now. And C2x might be right around the corner. A third edition of the book
won't be that bad.

[http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2021.htm](http://www.open-
std.org/jtc1/sc22/wg14/www/docs/n2021.htm)

~~~
sohkamyung
There are other books on C besides K&R. My current reference is _C: A
Reference Manual, Fifth Edition_ [1], which I usually pull out when I need to
check on syntax and standard libraries.

\- [http://careferencemanual.com/](http://careferencemanual.com/)

------
adrianN
Isn't K&R's book littered with code examples that were canonical in the 80's
but have glaring security holes? I wonder whether it's a good idea to have
students work through "the bible". Hopefully they provide extensive exegesis
in the lectures.

~~~
aisofteng
Introductory programming language texts do not concern themselves with
"security holes" usually. This is a strange criticism.

~~~
adrianN
Teaching C without teaching buffer overflows and undefined behavior is
reckless.

------
nickpsecurity
Most of this just says C was a popular implementation language following
UNIX’s fame. So, many things are written in C. So, knowing C will help you
understand how they work. People doing cutting-edge work that pick C are
usually clear that they pick it for compiler and talent availability, not
technical superiority for problem at hand. Now for the No’s. You don’t need to
know it for systems programming as plenty of better languages exist for that.
It barely contributed anything to good programming languages compared to
ALGOL, Simula, Modula, or LISP. Many key designs pushing OS’s forward were not
in C: Burrough’s ALGOL, IBM’s PL family, MULTICS in PL/0 & BCPL (UNIX started
as MULTICS subset), VMS in BLISS, LISP machines in LISP, Smalltalk-80 in
Smalltalk-80, Oberon systems in Oberon dialects, Spin in Modula-3, JX in Java,
and recently unikernels in Ocaml.

So, C is a necessary evil if you want to understand or extend legacy systems
whose authors preferred C. It’s also trendy in that people keep it mostly like
it is while defending any problems it has. That’s a social thing. Like COBOL
and PL/I are with the mainframe apps for companies using them. It’s not the
best language for systems programming along a lot of metrics. One doing clean-
slate work on a platform can use better languages to do better in the long-
term. Short-term benefits matter, though, so such projects often compile to C
or include C FFI to benefit from legacy stuff.

------
Annatar
While everything that the author wrote is true, and I will forever love C,
sometimes I wonder if I didn't get short changed by never having been taught
ANSI Common LISP at the university.

 _LISP is worth learning for a different reason — the profound enlightenment
experience you will have when you finally get it. That experience will make
you a better programmer for the rest of your days, even if you never actually
use LISP itself a lot._

[http://www.catb.org/~esr/faqs/hacker-
howto.html](http://www.catb.org/~esr/faqs/hacker-howto.html)

Functional language? Check. Stateless? Check. Reentrant? Check. Has a compiler
which can generate machine code ELF binary executables? Check.

That's not to say one shouldn't learn C - after all, C is the contemporary
portable assembler. But if one should also learn C, one should learn assembler
too, preferably on a processor with an orthogonal instruction set
architecture, like a Motorola 68000. Understanding both, we come back to the
author's point - without understanding how the machine works, fast, small,
efficient and elegant software will remain forever elusive.

------
partycoder
Ada and Pascal are not dead and are viable alternatives to C. If you don't
know them, check them out.

The C philosophy "the programmer knows what they're doing" does not
necessarily scale. It works when your team is strong or well supervised, but
if that is not the case due to location, budget or whatever reason, unless you
can afford a static analysis tool like Klocwork that can weed out mistakes
while not sacrificing productivity, by going low level you have picked a hard
battle.

C gives you a lot of power, but also a lot of rope to hang yourself with. I
don't even want to imagine what kind of apocalypse I would see if you give
multithreading and memory management powers to the caliber of people I've seen
recently.

------
fauigerzigerk
C has one quality that no other language has. You can write libraries in it
that can easily be used from all other languages on every platform.

~~~
pjmlp
That is only true if the OS was written in C.

What many wrongly call the C ABI is actually the OS ABI.

~~~
fauigerzigerk
The ABI is certainly helpful, but I don't think it's the only reason why C
libraries are easier to call than libraries written in other languages. C
doesn't have generics, inheritance or a GC, all of which make integration a
lot more difficult.

~~~
pjmlp
A set of features shared by many other, safer, system programming languages.

Their OSes didn't had a C ABI, rather an ESPOL, NEWP, Modula, and so forth
ABI.

~~~
fauigerzigerk
Sure, theoretically there could be viable alternatives to C.

~~~
pjmlp
What makes many of us sour, is that it isn't theory, rather already proven in
the past, back when C was only a UNIX language and barely relevant outside it.

It was the commoditization of UNIX in the industry that pushed C outside UNIX,
just like we nowadays have JavaScript outside the browser.

~~~
fauigerzigerk
It sounds remote today, but you're right that it didn't have to be this way.

What should make you even more sour is that another opportunity for starting
over seems to have been passed up when Google only recently chose to build
Fuchsia on top of a C++ based kernel.

------
anta40
>> Learning about operating systems would be much harder without C. The
operating systems that we use are mostly written in C, the C standard library
is tightly coupled to the syscall interface, and most resources dealing with
operating systems concepts assume knowledge of C.

I wonder what if Kernighan, Ritchie et all decided to write UNIX in Pascal,
not in C.

Hmmm.... :D

~~~
unwind
I don't think that was ever very likely, it kind of seems like Mr Kernighan
didn't _like_ Pascal: [https://www.lysator.liu.se/c/bwk-on-
pascal.html](https://www.lysator.liu.se/c/bwk-on-pascal.html). I'm not at all
clear about the detailed timeline, but this link is a pretty good answer to
that thought. :)

~~~
Roboprog
It's a shame Modula wasn't available until the early 80s (as far as I know),
but unfortunately, you are right.

C _is_ vastly preferable to writing assembler on multiple platforms, though.

The real tragedy is IT Managment(TM), which insisted on C++, and after that
inevitably failed (for most things outside of video games), insisted on Java
due to all the core dumping craziness.

Can't find the original source doc, but here goes:
[https://blog.acolyer.org/2016/09/07/the-emperors-old-
clothes...](https://blog.acolyer.org/2016/09/07/the-emperors-old-clothes/)

At least K&R took quicksort(), even if they didn't take the array subscript
bounds checking part (etc) to heart.

~~~
Roboprog
One other C inspired tragedy: WHY, OH WHY, did they insist on putting
identifier names _AFTER_ (most of) the type information???

Algol had it right, why screw it up?

I guess it doesn't matter if your (optional) type is word^H^H^H^H int, but
this has descended into chaos in Java land.

------
jimjimjim
if anything c is more popular now than 5-10 years ago. not c++ but normal c.
especially with the pendulum swing away from oo

it's almost an ideal hipster language.

~~~
sidlls
Ugh, that's the last thing I want to see. I didn't start diving into Rust
until very recently for two reasons: 1) the instability of the language and 2)
the terrible, juvenile hatred for C and C++ that seems to almost be a pre-
requisite for participation in the ecosystem. Rust until recently was an
anti-C hipster's wet dream ("upstart"-y, not really yet ready for wide-spread
use, and a convenient goto for folks wanting to have a bit of trendy "bash C
(or C++)" fun.

Both items have diminished considerably lately, though, and that's something I
can appreciate.

~~~
Manishearth
> the terrible, juvenile hatred for C and C++

I'm surprised (and sorry) to hear that. The Rust community tries very hard to
avoid language zealotry. If you see it on any of the Rust forums (can't speak
for other sites), please report it.

I've seen lots of well-reasoned complaining about UB and other issues that
C/++ are prone to, but not much juvenile hatred.

------
ninjakeyboard
Contrast with [http://chrisdone.com/posts/dijkstra-haskell-
java](http://chrisdone.com/posts/dijkstra-haskell-java)

~~~
tempodox
Very good reading, including the two links after the transcript.

I feel that both the OP and Dijkstra are right in their own respective way.

I do hope that Rust, for one, will turn out to be part of a path to better
practise.

------
quantum_state
Besides the reasons already listed, one more is C can be used to program
almost all of the micro controllers, an essential electronic element in modern
life.

~~~
tdb7893
With GHz level processors getting so cheap and developer time being so
expensive, I wonder if that will always be the case. I've recently moved from
using microcontrollers and C to using raspberry pi and beaglebone with python
and it's made my hobby projects more pleasant. I'm curious about whether I'm
going to run into issues later, though.

~~~
ArkyBeagle
It'll always be the case because of size-weight-power constraints. I have a
project on right now where we need it to run on a CR2032 style coin cell for
year or two.

The OO nature of Python can also get in the way of certain things.

------
musha68k
Nobody is "forsaking" C.

As mentioned in the article it is still a good way to learn about computers
and it's the true "lingua franca" of our times - that said it needs to be put
to rest for infrastructure software _now_.

I for one welcome our new Rust writing overlords.

------
conjectures
While K&R is a nice book, it's really not sufficient to become productive with
C. IIRC it doesn't cover things like make, valgrind and libraries. There's a
book 21st Century C which does the job of addressing that.

~~~
Roboprog
I ended up with a book, back in the late 80s, called (I think) "C, An Advanced
Introduction". To me, the K&R book was just too "circular", as the authors
were too close to the subject.

------
ArkyBeagle
"Most of our students use interpreted languages with popular implementations
written in C."

Well, guess what? Most of the 'C' code I've written in the last ten years
pretty much reflects the selfsame reality - next to nothing is done directly
in 'C' but rather as posts of "transactions" to an interface. These may or may
not be in text form but it's not much work to make 'em be in text form.

By the way - 'C' is excellent for text manipulation, even using the crufty old
library calls.

If you do this and you do it carefully, all the horrors of 'C' become at least
manageable. Done carefully enough, you don't even need all the new "safety"
furniture.

I blame nobody for not wanting to do this, but can we at least self-identify
as "will" or "won't" and behave accordingly? 'C' is no bugbear and your
favorite interpreter can't save you from a bugbear that doesn't exist. When
problems occur, it's because people didn't take the fifteen minutes or fifteen
seconds to prevent them.

I just find myself gobsmacked that people feel so utterly powerless against
the language.

------
Marazan
C helps you think like a _certain 1970 's abstraction of_ a computer.

I really hate the "C is how a computer really works" argument in favour of
learning C.

~~~
Rusky
That 1970s abstraction is certainly closer to modern computers than any higher
level language, and is quite a nice introductory route to learning more
accurate models.

We still start with the Bohr model in chemistry for the same reasons.

------
bryanlarsen
Do you teach assembly language too? It's a lot better at #3 (teaching you to
think like a computer) than C is, and it makes it a lot easier to fully grok C
concepts like the strange equivalence between pointers and arrays, between
character arrays and strings, et cetera.

C is trivially easy to learn if you know Assembly Language plus any other
imperative language.

My school taught assembly language as a full semester course (along with other
low level concepts). That and an intro to computers course that used either
Pascal or Fortran were requirements for the 200/300 level courses on operating
systems etc. that used C but didn't actually teach it. They made seminars
available for those who wanted to be taught C rather than having to learn it
themselves. I believe that this is the right approach.

Of course, soon after I went through they fell victim to the hype wagon and
switched to Java.

~~~
varjag
From TFA:

> Most engineers should take head of reason three, although our students also
> learn computer architecture and at least one assembly language, so have a
> firm mental model of how computers actually compute.

~~~
bryanlarsen
Thanks, I missed that. Do they learn assembly language before or after they
learn C? Are they explicitly taught C or do they learn it while using it in a
course like Operating Systems or Data Structures?

------
AstralStorm
To an extent, so does C++ help think like the machine, but you can skip a lot
of syntactic red tape. Until you get to advanced uses of templates.

It is also useful in order to show how those "smart" things in higher level
languages work, using standard library as examples.

------
kensai
C + Lua == 21st Century "C Programming"

There is no silver bullet for everything, obviously, but for me the above
combination is a match made in heaven. Lua is small and adds only the
necessary tools to take care of higher abstrations in many different
paradigms.

Even if these two are different languages, they are amazingly complementary. I
feel that a good introductory CS course could simply teach in one semester C
and the next Lua. By the end of the year students will be able to tackle a
huge amount of problems, as well as learned a useful systems and scripting
language.

~~~
anthk
C + Scheme (with Guile) can be more fun. Try it.

------
sargun
So, I quite like C. I don't use it very often, but I think that it's like a
sharp knife.

I don't quite see the point of C++ though. Can someone explain me why we
should continue to bow into it?

~~~
RossBencina
If you want a C-level sharp knife, and you want to work with abstraction (not
just OO and abstract data types, but also generics and metaprogramming), then
C++ is one of the few choices. D is maybe another option (if you can live with
GC). Maybe in the future also Rust, but my impression is that the Rust
generics and metaprogramming story is not quite there yet. C++ is mature, so
it's a safe choice in that respect: large installed base, ISO standardised,
mature tooling with multiple vendors.

If you don't need the C-level sharp knife, then there are a lot of options --
and a lot of reasons to choose them over C or C++.

Personally, I value that C++ is multi-paradigm (I can use classes when they
are a good fit, generics when they are a good fit, asm when it's a good fit,
etc.), also: trivial interop with C and assembler, no GC, runs directly on the
metal. These are reasons to use C++, but not necessarily reasons to "continue
to bow into it."

Did I mention generics and metaprogramming? Even if you don't use these
directly, their availability makes for flexible and powerful libraries. The
STL container library is the obvious example, but modern C++ metaprogramming
goes way beyond that.[0]

[0] For example, see Hana: CppCon 2015:
[https://www.youtube.com/watch?v=cg1wOINjV9U](https://www.youtube.com/watch?v=cg1wOINjV9U)
[https://github.com/boostorg/hana](https://github.com/boostorg/hana)

------
drvdevd
So I dropped out of college long ago and it is actually so ironic and yet also
refreshing to me to hear this viewpoint from a college professor. What a
beautifully explained rationale for a subject that I find so hard to
articulate to my colleages in our echo chamber. I'll definitely be pointing to
this in the future.

------
mankash666
Quick question: would the c loving crowd like an AWS lambda type offering
supporting coding in C? You know, to quickly supplement your embedded projects
with some intelligence and data processing on the server side, without having
to learn a new language or fussing with server infrastructure and scaling

~~~
PaulRobinson
Getting serverless PAYG patterns working in any language is going to be
useful.

Thing is, this exists. It's AWS Lambda. It allows running of arbitrary
executables in the sandbox: [https://aws.amazon.com/blogs/compute/running-
executables-in-...](https://aws.amazon.com/blogs/compute/running-executables-
in-aws-lambda/)

~~~
mankash666
What you mention has more overhead that being able to directly run in the main
process. Though, I don't know if it's noticeable for most use cases,
especially given how fast processors are today

------
zeveb
> It is still one of the most commonly used languages outside of the Bay Area
> web/mobile startup echo chamber

 _Is_ C all that commonly used these days? I rather suspect that it's an
unforced error to start a new project in C, and that many wise organisations
are replacing buggy C software with slightly-less-buggy software in safer
languages.

> C’s influence can be seen in many modern languages

True, but … is this actually that important in a learning situation? Knowing
Java will help learning Go (or vice-versa) about as much as learning C would,
I think.

> C helps you think like a computer

Like _a_ computer, sure, just not like _the_ computer actually running on
one's desk or in a data centre. Modern computers really aren't anything like
the C model.

> Most tools for writing software are written in C (or C++)

I suppose that's true, because lots of people have used C, and that really is
a good reason to know enough to get around in it, but … maybe one should teach
students to use better tools in better languages (Lisp & SmallTalk come to
mind).

Seriously, in 2016 it's obvious that C is just wrong.

~~~
jly
> Is C all that commonly used these days? I rather suspect that it's an
> unforced error to start a new project in C, and that many wise organisations
> are replacing buggy C software with slightly-less-buggy software in safer
> languages.

It most definitely is. Outside of the fact that existing huge projects are
written in C (Linux, many compilers/toolchains, databases, etc), it remains
the default language for embedded systems. Most smaller embedded device (think
Cortex-M class) is running code written in C. This represents an enormous
amount of projects spread over dozens of industries and use cases. Someday
that may change but right now even C++ has failed to gain traction in these
environments.

> Seriously, in 2016 it's obvious that C is just wrong.

This is not true. It all depends on your use case. C is the most well-
understood language on the planet - a sort of defacto default. Practices,
processes, and tools have been developed over decades to help mitigate
problems, often in systems that run for years without SW updates. This can't
be discounted.

~~~
pjmlp
Hence why the CVE database gets updated daily with memory corruption exploits.

------
CocoaGeek
'C' stickers do exist:
[http://www.unixstickers.com/stickers/coding_stickers/c-progr...](http://www.unixstickers.com/stickers/coding_stickers/c-programming-
language-shaped-sticker) 8)

------
kabdib
Is C really this disparaged in Silly Valley?

~~~
alfalfasprout
Yes. Keep in mind the vast majority of people on HN only work on end-user
software (native and web apps). Yes, there are _much_ better choices for the
web when you need security, etc.

In certain enterprise applications C are still the best choice. In finance,
where I work, C and C++ still reign supreme. Why? There's already a huge
multitude of great libraries developed over decades that are mature and
battle-tested. Sure, you can write bindings for Rust/Go/D/whatever. But that's
a ton of work for minimal benefit.

Fact is, when you get on a plane the avionics software was likely written in
C. NASA extensively uses C. The automotive industry extensively uses C. Oh,
and a lot of this C is embedded so forget easy software updates.

I think a lot of the hate for C comes from the fact that it lets you do bad
things without alerting you. C is a language that mandates solid engineering
practices. A good C codebase can be elegant, correct, and fully testable. The
language doesn't force this, however. But a nice, well written C library will
stand the test of time.

~~~
kabdib
Pretty much what I thought. (I've been programming C since 1979, and C++ since
1987, but left Silly Valley 15 years ago).

------
jorangreef
"Early in the morning he [Jesus] came again to the temple. All the people came
to him, and he sat down and taught them. The scribes and the Pharisees brought
a woman who had been caught in adultery, and placing her in the midst they
said to him, “Teacher, this woman has been caught in the act of adultery. Now
in the Law, Moses commanded us to stone such women. So what do you say?” This
they said to test him, that they might have some charge to bring against him.
Jesus bent down and wrote with his finger on the ground. And as they continued
to ask him, he stood up and said to them, “Let him who is without sin among
you be the first to throw a stone at her.” And once more he bent down and
wrote on the ground. But when they heard it, they went away one by one,
beginning with the older ones, and Jesus was left alone with the woman
standing before him. Jesus stood up and said to her, “Woman, where are they?
Has no one condemned you?” She said, “No one, Lord.” And Jesus said, “Neither
do I condemn you; go, and from now on sin no more.”

The Bible is useful certainly not just for historical value, but for making
you wise for salvation. The Bible is God's master plan for forgiving you, and
restoring you to friendship with himself, through Jesus' suffering, death and
resurrection explicitly on your behalf. "Believing" in Jesus is not believing
whether he exists, or whether God exists. "Believing" in Jesus means not
claiming to be without sin, but rather acknowledging your sin, and trusting
Jesus' work on the cross alone to save you from it.

~~~
jasonkostempski
If you believe it's god's master plan how do you choose weather to stone
adulterers or not stone adulterers? It says you should do both. I'm hoping
your answer will help me choose where to put my open braces.

~~~
duncan_bayne
Unfortunately, Islam has an answer to this sort of question - the doctrine of
abrogation. Basically, all conflicts are to be resolved in favour of the
latest version.

I say unfortunately because this gives precedence to the Medina verses, which
are marked by cruelty and violence.

------
justinlardinois
> The _most recent_ edition of the canonical C text (the excitingly named _The
> C Programming Language_ ) was published in 1988; C is so unfashionable that
> the authors have neglected to update it in light of 30 years of progress in
> software engineering.

This is an odd argument. C has hardly changed or evolved since 1988, so
there's not really a need for a new edition.

~~~
vu3rdd
The essence of the language has not changed. But C99 came out with a few nice
things. There is also C11 which brought in a few new things as well. It would
have been nice to bring the book up to C99.

"Modern C" is a good book on some of the new features.

    
    
        http://icube-icps.unistra.fr/img_auth.php/d/db/ModernC.pdf

~~~
justinlardinois
After reading up on C99 I take back what I said. I definitely thought some of
those features were older than they are.

