Live data from Hacker News

C’s Biggest Mistake (2009)

digitalmars.com

331–340 of 382 posts

Re: C’s Biggest Mistake (2009)

#331
>"What mistake has caused more grief, more bugs, more workarounds, more endless hours consumed, etc., than any other? Many people would say null pointers. I don’t agree.

Conflating pointers with arrays.

I don’t mean them using the same syntax, or the implicit conversion of arrays to pointers. I mean the inability to pass an array to a function as an array, even if it is declared to be an array. C will silently convert the array to be a pointer, and will rewrite the function declaration so it is semantically a pointer:

[...]

This seemingly innocuous convenience feature is the root of endless evil. It means that once arrays leave the scope in which they are defined, they become pointers, and lose the information which gives the extent of the array — the array dimension. What are the consequences of losing this information?

An alternative must be used.

For strings, it’s the whole reason for the 0 terminator.

For other arrays, it is inferred programmatically from the context. Naturally, every situation is different, and so an endless array (!) of bugs ensues.

The trainwreck just unfolds in slow motion from there.

The galaxy of C string functions, from the unsafe strcpy() to sprintf() onwards, is a direct result. There are various attempts at fixing this, such as the Safe C Library. Then there are all the buffer overflows, because functions handed a pointer have no idea what the limits are, and no array bounds checking is possible."

PDS: The root of all of this -- is that C, being a low-level, close-to-the-hardware, designed in the 1970's programming language (some in academia pejoratively call it a "glorified assembler"), was not designed with a proper string storage class as we know them in programming languages today; instead, arrays of characters were substituted for this purpose, and those arrays were not implemented containing total size (length) and dimensionality information.

Basically an array in C -- is a set of contiguous memory, which has a starting address (the pointer passed), and a stated element size that the compiler knows about, but not the length (aka, total size, element count, etc.) of that array, nor its dimensionality.

Observation: C's arrays need length information signalled in an out-of-band fashion (that is, this information cannot exist as a zero (0) -- somewhere in the array).

The irony of all of this is that C was invented at AT&T, and AT&T for the longest time had difficulty with phreakers exploiting 2600hz signals to gain access to its long distance trunk lines, from which they could call to anywhere in AT&T's system for free.

But, that's what the engineering error of in-band signaling generates...

C, by using arrays to implement strings, and letting the zero terminator (information about string length) exist in the memory space of the string, made exactly the same engineering mistake -- just in software -- and that is the mistake of in-band signaling.

Now, that being said, hindsight is 2020, and it couldn't be expected that Dennis Ritchie, who invented C in the 1970's would have foreseen the consequences of that engineering "mistake" (AKA, "act which generated quite the education for a future populace". ).

Such is the price of being an innovator.

On the one hand, he advanced computer technology greatly -- far beyond the technology advancements created by most of his contemporaries of his day...

On the other, that advancement gave us this highly educational engineering "mistake" -- that we can all learn from!

Such is the price of being an innovator -- and pressing the "bleeding edge" of what is possible...

Humanity could not be advanced without such innovators, and the occasional future flaws (and the wisdom that comes from examining them in hindsight!) that their innovations generate...

Re: C’s Biggest Mistake (2009)

#332
post #313

Earlier quoted context omitted.

Thank you for the new knowledge that "eso" is pronounced similar to "iso" in some dialects of English, I didn't know that. However, the word "isoteric" is more correctly spelled (in non-phonetic spelling) as esoteric . The prefix "eso-" means "inside" in Greek, as in "esothermic", or "esophagus". The prefix "iso-" means "equal", as in "isomorphism", "isosceles", "isometric", etc.

Maybe dial back the sarcasm a notch or two?

Many apologies - I was not being sarcastic and I'm sorry that this is how my comment came across. As chongli says I'm a native speaker of Greek and I really didn't know how "eso" is pronounced by native English speakers. I've lived for 15 years in the UK and I'm still surprised to hear how people pronounce the more obscure words in their language (some of which come from Greek).

Re: C’s Biggest Mistake (2009)

#334
post #45

Earlier quoted context omitted.

That's because of sunk-cost rather than design. Thanks to LLVM and GCC you can happily write embedded code in a higher level language, but the vendors don't bother supporting it because a lot of embedded coding isn't really what we would call software (no tests etc.)

Toolchains are one side, but garbage collection and big standard libraries are also a big reason. Anything with under a MB of RAM has a choice of several modern languages, but it is still basically just C, C++, Rust, Lua or MicroPython.

D works fine on microcontrollers.

I don't think anyone was going to write their fridge's code in Haskell anyway.

Re: C’s Biggest Mistake (2009)

#335
post #307

Earlier quoted context omitted.

So what the improvements between C89 and C18 in regards to UB and security, for any ISO C compliant compiler?

Between c89 and c18 is close to 30 years. What about between c99 and c18? Is there anything you can think of? I think the _s() functions, advertised as security features, are a weak effort. Anything else come to mind?

Nothing really, if anything VLAs have proven such a mistake that Google lead an effort to remove all instances of VLA use out of the Linux kernel.

Also the amount of UB descriptions just increased and are now well over 200.

Annex K was badly managed, a weak effort as you say, given that pointer and size were still handled separately, and in the end instead of coming up with a better design with struct based handles, like sds, everything was dropped.

ISO C drafts are freely available, I recommend everyone that thinks that they know C out of some book, or have only read K&R book, to actually read them.

Re: C’s Biggest Mistake (2009)

#336
post #299

Earlier quoted context omitted.

The same is likely true of Fortran, since Fortran code is shipped around with several Python data science libraries and included in R. Does that mean Fortran is a thriving language, or does it just mean Fortran was used a long time ago to write some important libraries that are now hard to get rid of?

Except Fortran 2018 is quite modern, supports modules, generics, and even OOP, first class support on CUDA alongside C++, whereas C18 hardly changed since C89 besides some cosmetic stuff and it is as secure as when it got used to rewrite UNIX in the early 70s.

It could be argued though that less usage means fewer stake holders to convince of the need for specific changes to the language, which helps with increased evolution. (I have only cursory knowledge of what's happening in C and none about what's happening in Pascal nowadays, just pointing out that being a smaller community might ironically help the language).

Re: C’s Biggest Mistake (2009)

#337
post #168

Earlier quoted context omitted.

Try becoming a COBOL developer and see how that works for you. Likening C to COBOL isn't doing it any favors.

What's the implication here? I only know one COBOL developer but they seem to be doing quite well for themselves, making over $400k a year for something like 15 hours of work a week.

COBOL developers commanding a high salary is directly related to it not being a thriving language.

Re: C’s Biggest Mistake (2009)

#338

Earlier quoted context omitted.

C has been "losing ground" not because of random per peeves of those who never wrote a line of code in C but because since C's last standard update there have been other programming languages that offer developers something of value so that the trade-off between using C or any alternative starts to make technical sense. It also helps that C's standardization proceeds in ways that feel somewhat between sabotage and ut…

Maybe people are voting this down because they think it's directed at Walter Bright in particular, but I think there is actually some truth in the harsh comment. Nothing about Walter Bright in this statement, but some of the harshest criticisms from others I have seen of C are not from expert practitioners in C. People who are experts and also critics seem to have a more practical, realistic, nuanced critique, that u…

> some of the harshest criticisms from others I have seen of C are not from expert practitioners in C.

But were they expert practitioners of C in the past? My experience is that most of the harshest criticisms of C come from former C experts who moved on to other languages because it became clear to them that C would never be fixed - Walter Bright included.

Re: C’s Biggest Mistake (2009)

#339
post #318

Earlier quoted context omitted.

I must be a really really good programmer, since I rarely see the need to use strlen(). For one, strings are just chunks of memory like other arrays. So for almost any string that is not a literal in the source code, you just store offset/length as needed, like for any other array. I have sizeable projects (on the order of 10K lines) that have maybe 0 or 1 instances of strlen() in the code. Very often though, strings…

Look how many C library functions implicitly call strlen() internally. Also, look at functions like sscanf(). It can be orders of magnitude slower than fscanf() because every invocation calls strlen while fscanf incrementally reads from the current file pointer. I don't know why sscanf doesn't also work incrementally but the implementations I've tested don't do that. The main point here being: if strings had a size_t…

I checked musl libc and the way the implementation implements sscanf is by calling vsscanf with a custom FILE stream. And that file stream is implemented using __string_read(), which does indeed call strnlen().

I figure it would be possible for musl to implement that stream using a function that scans for NUL and copies at the same time, but maybe that's not an improvement in the end.

It would be much simpler of course if sscanf() would take the length of the input string as an additional argument. But actually, I don't really care.

Because, does this even matter? Using sscanf() is far from ideal anyway. The stdio functions are not what you use if you're going for performance. Their conversions are probably not the fastest (being quite featureful), and they are even locale dependent which is a huge mess!

Heck, when we're going for performance to a degree where a strlen() matters (bear in mind that we have to read the input at least once anyway, so the waste is definitely bounded) we should certainly not be parsing text at all. That is much more wasteful in comparison.

Much if not most of libc is there to provide you a portable base to (comparatively) quickly get your project up and running, and to simply to keep old software going, but it's certainly not to help you achieve performance.

http://git.musl-libc.org/cgit/musl/commit/?id=18efeb320b763e...

Re: C’s Biggest Mistake (2009)

#340
post #158

Earlier quoted context omitted.

Huh? In what way is C’s books, documentation or build system superior to that found in other languages? Most languages have plenty of good books written about them. And plenty of code examples online. I can’t speak for other languages but I find MDN (Javascript) and the rust docs consistently better than C’s man pages. Ruby’s documentation is great too. As for build systems, autotools is a hilarious clown car of a di…

> in rust “cargo build” will build my project correctly on any platform I've got a parts drawer full of controllers that says it won't.

You are conflating consistency of package management and library behavior across platforms with platform support.

When it comes to microcontrollers rust is currently at the mercy of LLVM support and vendors.

Post reply on HN