Live data from Hacker News

C’s Biggest Mistake (2009)

digitalmars.com

201–210 of 382 posts

Re: C’s Biggest Mistake (2009)

#201
post #130

Author here. I'll be blunt and repeat a prediction I made 3 years ago or so: C is finished if it doesn't address the buffer overflow problem, and this proposal is a simple, easy, backwards compatible way to do it. It is simply too expensive to deal with buffer overflow bugs anymore. This one addition will revolutionize C programming like adding function prototypes did.

> C is finished if it doesn't address the buffer overflow problem, and this proposal is a simple, easy, backwards compatible way to do it. Is this really "simple, easy, backwards compatible"? I think Rust kind of counterexamples this. While Rust can throw around slices [] (effectively runtime length), throwing around [u8; 8] and [u8; 9] (compile time length) to the same function gets nasty. Perhaps all the constexpr…

Not constexpr, this is solved by constant generics (the famous RFC 2000) with the array bound as a constant “generic” parameter/value.

I’ve been pushing for this feature for many years and have been playing with it since it first landed in nightly. It works quite well.

Re: C’s Biggest Mistake (2009)

#202
post #34

Earlier quoted context omitted.

> lack of package manager, common build system, good documentation. This is where C is superior to virtually every other language. It has K&R to start with [1], a wealth of examples to progress from there, man pages, autotools, cmake, static and shared libraries. > good standard library. It should have hash tables at least, but it isn't bad. [1] Which is still the best language book ever written (yes, it has some ant…

> It should have hash tables at least https://man.openbsd.org/ohash_init.3

What of it?

> Those functions are completely non-standard and should be avoided in portable programs.

Re: C’s Biggest Mistake (2009)

#203
post #90

Earlier quoted context omitted.

The higher level languages are kind of the problem though. I need things like the ability to know the layout of my structs.

Rust, D, Whatever let you control the layout of your struct.

Even C#, actually!

Re: C’s Biggest Mistake (2009)

#204
post #117

Earlier quoted context omitted.

on a somewhat related note, I've always wished for something like `explicit` that prevents assigning different typedefs for the same underlying type to each other. like suppose I have two types, WorldVec (vector in worldspace) and ViewVec (vector in view/sceenspace). under the hood they are both typedefs for float[3], so I can freely assign them back and forth. but any vector operation that mixes the types would almo…

This has always bugged me as well. I've generally solved this by wrapping things in a struct. Type checking will use the (incompatible) wrappers and a modern compiler should optimize them away. To avoid strict aliasing violations when converting between equivalent wrapped types you can use a union and employ a function to hide the verbosity. I have no idea if this is the "right" way to do things, but it seems to work…

That's what Microsoft did from some version on in their build tools, all the HANDLE's etc used to just be typedef void , now they're a dummy struct each (HANDLE__ ). Seems to be a good solution.

Re: C’s Biggest Mistake (2009)

#205

The biggest mistake to me feels like implicit integer conversions. That's where C feels like it's really out to get you.

on a somewhat related note, I've always wished for something like `explicit` that prevents assigning different typedefs for the same underlying type to each other. like suppose I have two types, WorldVec (vector in worldspace) and ViewVec (vector in view/sceenspace). under the hood they are both typedefs for float[3], so I can freely assign them back and forth. but any vector operation that mixes the types would almo…

C is considered strictly typed but that’s only when compared to the likes of JS, Python, and co. What you’re taking about is incredibly important and using it in other truly strongly typed languages has opened my eyes to just how much compile time safety a language can really provide, practically free of cost.

Re: C’s Biggest Mistake (2009)

#206
post #169

Earlier quoted context omitted.

I don't see much point in it. I've proposed this change to C in front of several audiences, and it never received any traction. If you want to experiment with it, you can use DasBetterC, i.e. running the D compiler with the `-betterC` switch, which enables programs to be built requiring only the C Standard Library. Fair warning - once you get accustomed to DasBetterC, you're not likely to want to go back to C :-)

> If you want to experiment with it, you can use DasBetterC, i.e. running the D compiler with the `-betterC` I've been meaning to experiment with DasBetterC for a while, and I have a project C I've been wanting to migrate to something with proper strings (it's an converter for some binary file formats, but now I want it to import some obscure text formats too). Maybe that's the push I needed :) After 20 minutes and a…

Great!

DasBetterC's trial-by-fire was when I used it to convert DMD's backend from C to D.

I'm sure you already know this, but the trick to translating is to resist the urge to refactor and fix bugs while you're at it. Convert files one at a time, and after each run the test suite.

Only after it's all converted and passing the test suite can refactoring and bug fixing be considered.

Re: C’s Biggest Mistake (2009)

#207
The C standard doesn’t forbid fat pointers. You could have a compiler that implements fat pointers (and crashes on out of bounds access attempts) without violating the standards in any way, since our of bounds accesses are undefined behavior.

Re: C’s Biggest Mistake (2009)

#208
post #130

Earlier quoted context omitted.

> C is finished if it doesn't address the buffer overflow problem, and this proposal is a simple, easy, backwards compatible way to do it. Is this really "simple, easy, backwards compatible"? I think Rust kind of counterexamples this. While Rust can throw around slices [] (effectively runtime length), throwing around [u8; 8] and [u8; 9] (compile time length) to the same function gets nasty. Perhaps all the constexpr…

Not constexpr, this is solved by constant generics (the famous RFC 2000) with the array bound as a constant “generic” parameter/value. I’ve been pushing for this feature for many years and have been playing with it since it first landed in nightly. It works quite well.

Sorry, I misspoke. But this wasn't meant to be about Rust.

My point was that: if you dump slices/fat pointers into C, how does it help?

Slices/fat pointers and the corresponding checks are a runtime thing, and that's absolutely anathema to a lot of C programmers. If it's not anathema to the C programmer, they probably aren't in C anyway.

So, now you need a way so that compiled slices/fat pointers mean something, and I'm not convinced that doesn't have a lot of ramifications that are being glossed over.

Re: C’s Biggest Mistake (2009)

#209

Earlier quoted context omitted.

> It should have hash tables at least https://man.openbsd.org/ohash_init.3

What of it? > Those functions are completely non-standard and should be avoided in portable programs.

Sure, it has not been standardized, it is not part of the standard library, so what? Did the world stop? I mean, practically speaking, who cares? Implement it, or find libraries that did. There are plenty. I posted this one because it exists for an OS; OpenBSD, since 1999. Plus, AFAIK ohash is portable enough. It consists of 2 files, and you can compile it with -std=c89. Only the bounded attribute is ignored.

If you want I could have brought up hcreate, hdestroy, and hsearch:

> The functions hcreate(), hsearch(), and hdestroy() are from SVr4, and are described in POSIX.1-2001 and POSIX.1-2008.

Happier?

Re: C’s Biggest Mistake (2009)

#210
post #161

I don't see a mistake here, certainly not a "biggest mistake". This is C, not C++. Keep it simple. Here, the idea is that there is no special type for "pointer+size" (what the author proposes as an array). Ok, let's add one and see the implications. - How do I get the size, the number of elements? A "sizeof" like operator? - Can I resize the array? If yes, how? If no, why? - What happens if I overflow? Undefined beha…

> How do I get the size,

    sizeof(array)
> the number of elements?

    array.length
> Can I resize the array? If yes, how? If no, why?

In D it would be:

    T* p = realloc(array.ptr, newLength * sizeof(T));
    array = p[0 .. newLength];
A C macro could handle that in C.

> What happens if I overflow?

2's complement arithmetic happens.

> A memcpy-like would be an obvious function to implement, what happens if sizes differ?

That would be up to the implementor of the function. There are many ways.

> What is the relationship between static arrays (ex: int a[5]) and "pointer+size" arrays? Are these completely different types?

Yes, they are different types.

> Is there an implicit cast bet>ween the two?

Conversion between a static array and the dynamic array should be implicit. Can't go the other way.

> About casting, how can I go from a separate pointer and size to an array and vice versa? If it is possible at all.

In D, this would be:

    a = p[0 .. size];
In C, I expect a macro can do it:

    a = ToArray(p, size);
> What if I do a bit of pointer magic to access the internal representation of the array?

Then you'd need to be careful to do it right, as in any systems language when you go under the hood.

> using mem* instead of str*

That only works for some functions. Not fopen(), for example.

> or %.*s

I use that a lot, but it's annoying because the length argument must be an int, and so must be cast from size_t.

Post reply on HN