
Some Were Meant for C (2017) [pdf] - chauhankiran
https://www.cs.kent.ac.uk/people/staff/srk21//research/papers/kell17some-preprint.pdf
======
aap_
I don't like how people on the internet hate on C all the time. To me C is a
wonderfully simple and elegant language that I can most of the time very
clearly express my thoughts in. I find that this not the case with many other
languages. This is the reason I use C. Of course compiler writers are trying
to sabotage this but I don't write any critical code so if I get hit by an
occasional bug it's not a big problem. I think C is misunderstood, perhaps
because it is used everywhere and standards for critical pieces of software
are applied to non-critical ones. E.g. never freeing memory, even leaking it
by destroying all references to it, can be totally fine if your program just
runs for a few seconds. Just allocate what you need, throw it away, and let
the OS clean up when you're done. This is perfectly fine but I feel like many
people wouldn't accept this kind of code because it's not acceptable in other
circumstances.

Anyway, the author makes a few good points that are important but often
overlooked, but I don't think I'd agree with him on the safety aspect in
section 6. Making a safe C implementation doesn't really appear possible. If
you allow casting integers to pointers, how do you implement these saftey
checks he's talking about?

~~~
GlennS
I feel like C has to go in the bucket of 'bad languages' these days, because
it doesn't have sensible unicode support built in.

But that doesn't mean you can't have fun with it, or write good computer
programs.

It just means that user inputted text is always going to be a pain.

~~~
Nursie
To be fair it doesn't really have strings 'built in' particularly well either.
It directly manipulates memory patches, and the string support that is there
is mostly a very simple abstraction on that.

If you want support for unicode etc, there are libraries.

~~~
solarkraft
But then that brings you compatibility issues, overhead ...

~~~
Nursie
If you want to avoid development overhead, absolutely, C is a terrible
language to pick.

I'm not sure what you mean by compatibility issues in this context?

~~~
solarkraft
I'm thinking about differen string representations used by different
libraries. Is this not true?

~~~
Nursie
Honestly all I've encountered default strings (and people shy away from those
now) and LibICU stuff. I think ICU has become a defacto standard but I have
been out of C for a few years.

This tends to be important for strings you're going to show to the user (or
input you gather from them), maybe most of the C in the world isn't aimed at
interfaces like that...

------
sevensor
I will always have a soft spot for C. It was my first language. I wrote my
first linked list in C. 30 seconds later I had my first segfault. C was the
entrance to the rabbit hole for me. I went down through assembly language,
down through logic design, circuit design, and transistor theory, all the way
down to fabrication and quantum mechanics. It was a long time before I came
back from that trip. Today, I wouldn't use C for everything, or even for many
things, but I'm glad I know it and I'm glad it's the substratum that holds
most everything else together.

I'm glad because C is an idea you can hold in your head. I can look at old C,
I can look at new C, and it's all pretty sensible. (Excepting macro abuse,
deliberate obfuscation, or gross incompetence.) It's hard to say that about
most any other language.

------
millstone
What is lovely about C is its paper-thin layer atop the syscall pokey bits:
signal, vfork, mmap, etc. No surprise that other languages either start by
using libc, or find their way there eventually.

~~~
bluetomcat
The "killer feature" of C is the simple semantics of the language (despite all
the dark undefined corners), which can be implemented relatively
straightforward on a variety of ISAs. There isn't any need for runtime support
because of the lack of fancy language features.

That makes it the most natural way to call into the operating system, without
any concerns that the chunk of memory returned by mmap has to be somehow
managed by the language runtime.

~~~
pjc50
The trouble is you can step from simple semantics to dark corners through such
simple things as "adding two numbers together" and "accepting user input". I
do agree that the lack of need for a managed runtime is a huge advantage on
embedded or small systems.

~~~
bluetomcat
> I do agree that the lack of need for a managed runtime is a huge advantage
> on embedded or small systems.

Not only in embedded systems. It is a huge advantage when interfacing with the
operating system from within a userland process.

Lack of a runtime means that a call to a kernel function like, say,
`sched_setscheduler(2)` would not interfere with any such thread scheduling
policies of the host runtime. Or that the runtime is grabbing file descriptors
out of your control, making it hard to reason about resource usage.

------
lone_haxx0r
If C didn't have (as much) undefined behavior it would be practically perfect.
There's not much else that I would change about it.

~~~
sgillen
Honest question. What has stopped people from creating a standard with no
undefined behavior? Is such a thing impossible? Have people done it?

~~~
uasm
> "What has stopped people from creating a standard with no undefined
> behavior? Is such a thing impossible?"

I don't understand the "undefined behavior" bandwagon.

1\. We have a perfectly defined list of "undefined behaviors".

2\. Said list also happens to be relatively small and scoped.

3\. "Undefined behaviors" exist because the language can't make certain
runtime guarantees which are largely dependent on
compiler/os/platform/hardware-specific promises. If you have to, just roll in
your own runtime checks. C won't force those on you...

~~~
johannes1234321
The language could make those guarantees if it wanted to. This might add
overhead on some architectures, but would be possible. An example is integer
overflow. If we limit to machines using two's complement (thus any machine
architecture used during last thirty years) this could be fully defined
easily. And if C is ever used on a other architecture they could build a
workaround using some form of oberflow trap. (Since CPU design would take C
into consideration)

Or evaluation order - `i = ++i;` could easily be defined in some way. But
might prevent some niche optimisations by the compiler.

Of course by C's nature there are limits (C won't be able to detect use after
free or similar without changing language notably) but there is room where UB
could be reduced, if it was seen as neccisary.

~~~
uasm
> "The language could make those guarantees if it wanted to"

> "Of course by C's nature there are limits"

You seem to acknowledge the fact that most of the undefined behaviors in C are
essentially born out of compromise. Those compromises were driven by
principles such as "keep the power in the hands of developers", "don't impose
unnecessary restrictions", "keep the language clean", "avoid hidden runtime
magic". The end results reflect that.

As I've mentioned in my previous comment, there's no "one size fits all", so
the language makes it trivial for you to roll out your very own runtime magic
(à-la Zig/Nim) which suits you best. Why is that a bad thing?

------
MaysonL
The only reason C is as popular as it is is that it was used to write Unix,
which was widely distributed and implemented. The rest is just following on
that. It's just like the reason human (and other mammals) have their optic
nerve passing through the retina creating a blind spot: pure historical
accident.

~~~
oytis
Yes and no. It can explain why C dominates over other low-tech languages, like
e.g. Pascal. But when people talk about replacing C they usually mean
replacing it with some feature-rich language. And why C survives and dominates
certain areas despite lacking all the fancy features is a totally different
question.

~~~
C1sc0cat
Pascal isn't a low level language its a teaching one

~~~
_0ffh
That's an age old discussion.

The practical Pascal variants like Turbo Pascal and Quick Pascal, which
compiled to native code, are essentially on par with C regarding the features.
That includes access to absolute memory addresses, port I/O and the speed of
the resulting code. I've done over a decade of Turbo Pascal coding, and going
on three decades of C, and I agree they feel like essentially much the same
thing.

~~~
C1sc0cat
Humm ok but sounds risky I can recall PET programming where you would poke raw
assembly code and BBC basic could inline Assembly , not sure that means BASIC
is a low level language.

------
kosma
Obligatory (and hilarious) read: "The Night Watch"[0] by James Mickens.

> You might ask, “Why would someone write code in a grotesque language that
> exposes raw memory addresses? Why not use a modern language with garbage
> collection and functional programming and free massages after lunch?” Here’s
> the answer: Pointers are real. They’re what the hardware understands.
> Somebody has to deal with them. You can’t just place a LISP book on top of
> an x86 chip and hope that the hardware learns about lambda calculus by
> osmosis.

[0][https://www.usenix.org/system/files/1311_05-08_mickens.pdf](https://www.usenix.org/system/files/1311_05-08_mickens.pdf)

~~~
holografix
Got me LOL’ing several times! Thanks for sharing

------
roca
It's dumb that in 2017 the author doesn't say anything specific about Rust,
which is by far the strongest "C replacement" candidate.

The author doesn't deal with the problem that the "direct access to memory
without abstractions" style they love so very easily drifts into undefined
behaviour. It also optimizes very poorly due to lack of aliasing information,
unless you enable type-based alias analysis in which case accidental undefined
behavior is catastrophic.

The "dynamically checked C" they propose as a solution to C's safety issues is
no solution at all until you can get it to work in practice. A lot of really
great people, including the researchers he cites, have tried really hard to
make it work and have failed in practice. He doesn't seem to understand why
they failed or have any insight into how to overcome the problems.

------
dang
Discussed at the time:
[https://news.ycombinator.com/item?id=15179188](https://news.ycombinator.com/item?id=15179188)

------
e9
I would change it to: some were meant to c

~~~
jamiecollinson
From the intro it's a reference to a song lyric (which I wasn't familiar
with):

    
    
      While some were meant for sea, in tug-boats ’Round the shore’s knee,
      (Milling with the sand,
      and always coming back to land),
      For others, up above
      Is all they care to think of,
      Up there with the birds and clouds, and Words don’t follow.
      —Tiny Ruins, from “Priest with Balloons”

------
morenoh149
the other discussion mentions D as a better C.

Anyone ever try to build "C the good parts"?

~~~
oddity
They did. Many times.

First they made "C the good parts" by gathering all the various C bits then in
use to make something portable and called it C89.

Then they made "C the good parts" by removing all the parts that made C slow
to write and called it Perl.

Then they made "C the good parts" by making C easier but still fast and called
it Java.

In the meantime, we've gotten Objective-C and C++, which were attempts to make
C better while preserving backwards compatibility. C++ has gone on to spawn
its own legacy of "No actually, these are the good parts" with D, Clay, Rust,
and various half-steps along the way that want some of the features of C++ but
not all of the features of C++.

I don't think they'll stop, because as it turns out, people use tools for
different reasons and it's very rare that a general purpose tool solves your
very specific problem perfectly. I'm inherently skeptical of any "X the good
parts" because the "good parts" are domain specific.

~~~
tejuis
I agree. If you take the tool perspective, it is easy to understand that
different tools are needed for different tasks. Don't use hammer for sawing.
No single language scales to all corners of programming problems.

Actually I really don't get this endless "silver bullet" discussion. C has its
place and for very good reasons. Also the author makes really good points
about the integration aspects of C.

~~~
cjfd
I read this thought quite often here on hacker news but it is a bit alien to
me. To me the charm of programming is the ability to---at least in theory---
write anything. This is also embodied in the idea of Turing completeness.

There is a continuum between the possibilities of a programming language and
the possibilities of a configuration file. As soon as one says that a
programming language is suitable for a particular purpose one has moved a few
steps towards the configuration file end of this continuum.

This is, of course, a personal preference but I very much prefer to enjoy the
power of programming language as opposed to the lack thereof of configuration
files. Therefore, I like programming languages that attempt to be useful for
any purpose. My favorite language is still C++ and if I were to switch to
something else I would be inclined towards Rust.

~~~
Kaiyou
Somehow I was expecting Lisp instead of C++ after all you've said. Any
specific reason why you're not using Lisp?

~~~
cjfd
Well, the ability to program anything includes the possibility to do tasks
that require high performance. Also, I do like the fact that the compiler
guards the type correctness of the program.

~~~
tejuis
If your requirements are only high performance and improved type checking,
then you are all set. The only language you need is C++. But the criteria
above does not define all programming problems.

C++ is too complicated. "Nobody" writes C++, but a subset of it. Select your
subset.

Dynamic typing in Lisp (and the like) is really nice for quick prototyping
where program correctness is not key. You are exploring what you want to
achieve with the program, be it algorithm level or architecture. C++ is not
well suited for that, since type checking and memory worries are slowing you
down, too many details to drag along. Hence no "silver bullet".

~~~
cjfd
Sure, C++ is complicated. And the way templates are compiled is positively
weird, which in turn sometimes leads to long compilation times. The 'select
your subset' thing is often repeated, but I do not see much of that. I am a
bit worried, though, that C++ seems to keep growing to the point where it
really might get to big and complicated.

Quick prototyping is not something that I do. Nor am I very much interested in
it. At my place of work I have seen it done around me after which it was my
task to turn the python prototype into C++. The most surprising thing there
was how far the prototype turned out to be from what was actually needed, to
the point where I very much question whether the prototyping exercise was
useful at all. YMMV regarding this, of course.

~~~
morenoh149
A python prototype is useful for specifying the correct program behavior. It's
useful as a guide for later implementors. Better than a spec in a word
document.

------
danieltillett
The best thing about C (apart from speed) is that for every issue with the
language there is a tool that fixes the problem. It can do everything
everywhere even if it's sometimes not the best choice.

