Hacker News new | ask | show | jobs
by copsarebastards 4125 days ago
All of the examples here are really horrible code. This is the second article in a few days on Hacker News to list out a few examples of how hard C is. And for little reason; there's absolutely no value in being able to write something like:

    return ({goto L; 0;}) && ({L: 5;});
It probably has a bug, will be hard to debug, and isn't more performant than writing it in a clearer way. And unfortunately, while the examples here are probably all contrived, there are plenty of real-life cases where code as bad as this gets into production systems.

So why are we still writing code like this?

The answer is reverse compatibility. Not just of compilers, but of tools and skillsets: people are unwilling to support multiple versions of C and want their code to run forever.

Objective-C and C++ do things to add functionality to C, but they don't remove the functionality of C that allows these kinds of problems.

This points to a need for a new language that avoids these issues. I think Rust is the answer, but I would like to see more languages try to fill that gap--competition is healthy.

3 comments

> This points to a need for a new language that avoids these issues. I think Rust is the answer, but I would like to see more languages try to fill that gap--competition is healthy.

Programs written in C and C++ may have issues because the languages assume the programmer knows what they are doing. This assumption leads to some great solutions to hard problems because the programmer is essentially free to do what they want.

Of course, this assumption, as with most others, doesn't always hold true. This doesn't mean there is a problem with the language. The problem is with the programmer.

If you're going to write something like "return ({goto L; 0;}) && ({L: 5;});", no language is going to save you.

C and C++ are still used today, in part, because modern languages try to restrict the programmer. Rather than assume the programmer knows what they are doing, they assume the programmer is stupid and needs help to cross the road. By assuming stupidity, the restrictions modern languages put in place prohibit certain solutions and as such C and C++ will remain the go-to systems languages.

We do not need new languages. What we need is programmers who won't abuse the languages we already have.

> Programs written in C and C++ may have issues because the languages assume the programmer knows what they are doing. This assumption leads to some great solutions to hard problems because the programmer is essentially free to do what they want.

There’s an assumption here that it would be impossible to design a language which would make these solutions available without being as error prone. Existing languages may be less capable than C, but that’s only because equally capable languages with less risk haven’t been created (Rust may be a solution, I'm not sure yet).

What exactly do you think can’t be done in a language that is less error-prone?

> We do not need new languages. What we need is programmers who won't abuse the languages we already have.

You’re part of the problem. It takes incredible hubris to say something like this, to think that it’s even possible for a human to do this.

Every nontrivial networking program written in C has security holes caused by memory management issues. If you’re going to claim that these errors are caused by bad programmers, then every C programmer is a bad programmer, because every C programmer has written bugs like this. If you’re claiming that bugs caused by C’s error-prone semantics are programmers abusing the language, then using C is equivalent to abusing C. The very best programmers writing C write bugs in C that they wouldn’t write in a language like Rust.

A system which depends on humans being perfect is bound to fail. There’s simply no way you can reasonably debate this fact.

Every other engineering field has redundancy, multiple layers of error checking that catch errors.

Until you see this as a problem then you’re a danger to any mission-critical product you work on. Not understanding that using C is a risk displays a shocking level of naiveté for a professional in this field. I’m not saying C is never a good choice. I write a lot of C myself, but I do so with the awareness that my code is not being checked adequately and that I have to take extreme measures to ensure that my code is well-validated.

In Rust, programmers are also "essentially free to do what they want", you just need to explicitly declare the parts of your code where you know better than the type system. The pertinent difference is Rust is memory-safe by default, and forces you to opt-in to unsafety and undefined behavior so that those pieces of code in particular can be more closely audited.
This is odd, GCC documentation clearly states that jumping into statement expression is not permitted. It is properly identified as error when compiling as c file, but no errors are given when compiled as c++ file. https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
> This points to a need for a new language that avoids these issues.

They already existed back when C was UNIX only, but then UNIX became widespread....