Live data from Hacker News

The case against a C alternative

c3.handmade.network

361–370 of 388 posts

Re: The case against a C alternative

#361

You could write a 100-line python script that compiles from your custom language to C code and it's still be better than C. There's lots of ways to re-use existing tooling and the bar really isn't that high for better languages

Why do you think more of these projects don't take this approach? I would be 10x more likely to try one in a professional setting if I knew the portion I was taking chance on was source translation layer, and I could rely on the well tested and supported C infrastructure.

I was considering this for my programming language but I will most likely not use it because it makes optimisations and garbage collection harder, and the C would not be human readable (just look at the output of the chicken compiler for an example) so there's not a huge benefit. C-- could be an option but it isn't very active or well used.

In terms of relying on tested and supported infrastructure lots of these projects use llvm.

Re: The case against a C alternative

#362

Earlier quoted context omitted.

I agree filepath related tasks are ugly. But there are a number of reasons for that that aren't related to zero termination. First, there is syntax & semantics of filepaths. Strings (whatever kind, just thinking about their monoidic structure) are a convenient user interface for specifying filepath constants, but they're annoying to construct from, and disassemble into, filepath components programmatically (relative…

> Last time you were looking at a binary using your editor or pager, how much better has your experience been thanks to NUL terminators? Not perceptibly better. And yeah, I do look at binary dumps now and then, after all, I wrote the code that generates ELF, OMF, MachO, and MSCOFF object file formats, and librarians for them :-)

I wrote simple ELF and PE/COFF writers too, but independently of that, zero terminators are what lets you find strings in a binary. And what allows the "strings" program to function. It simply couldn't work with without those terminators.

Similarly, the text we're exchanging consists of words and sentences that are terminated using not zero bytes, but other terminators. I'm very happy that they're not length delineated.

Re: The case against a C alternative

#363

Earlier quoted context omitted.

I agree filepath related tasks are ugly. But there are a number of reasons for that that aren't related to zero termination. First, there is syntax & semantics of filepaths. Strings (whatever kind, just thinking about their monoidic structure) are a convenient user interface for specifying filepath constants, but they're annoying to construct from, and disassemble into, filepath components programmatically (relative…

> memory allocation, and this is arguably orthogonal to the string representations A substringz cannot be produced from a stringz without doing an allocation. > you're free to make substrings using pointer + length or whatever, and this is in many cases the best solution Right, I can. And it's an ongoing nuisance in C to do so, because it doesn't have proper abstractions to build new types with. Even worse, if I swit…

> You wind up with two string representations in your code, and then what? Have each string function come in a pair?

As said, I don't think this is the end of the world, and I'm likely to add a number of other string representations. While it happens rarely, I don't worry about formatting a temporary string for an API into a temporary before calling it. Because most "string" things are small and dispensable. Zero-terminated strings are the cheap plastic solution that just works for submitting string-literals to printf, and that just works to view directly in a binary. And they're compatible with length delineated in the sense that you can supply a (cheap plastic) zero-terminated string to a (more serious) length delineated API. Also the other way, many length delineated APIs are designed to work with both - supply -1 as length, and you can happily put a string literal as argument, don't even have to macro your way with sizeof then to supply the right length.

> The good news is there is a fix, and I've proposed it, but it gets zero traction

I'm aware of this and I like it ("fat pointers") but I wouldn't like it if the APIs would miss the explicit length argument because there's a size field glued to the slice.

Re: The case against a C alternative

#364
post #354
post #239

Earlier quoted context omitted.

Safety is a good reason. I like protection against leaks and use after free. If I’m already allocating I’m not going to worry about the little bit of extra performance cost the abstraction might have.

To be clear: I'm not advocating for the use of `new` / `delete` over unique_ptr. But if you're creating a local object that never has to leave the current scope (or a member variable that's never moved in or out), there's no benefit to using a unique_ptr instead of creating the object directly on the stack or inline as part of your class, where the object's lifetime is bound to the scope, and your destructor is autom…

I agree! You should use a regular object if possible, I’d never suggest otherwise. The rare exceptions I’ve run into are annoying initialization order issues (usually code that I didn’t have the time/knowledge/political credits to refactor) and large arrays that blow the stack.

Re: The case against a C alternative

#365
post #350

Earlier quoted context omitted.

If the choice is between a compile time warning and a runtime crash, I will take the warning every single time: much closer to the actual error. You're probably asking for a compile time error instead. Indeed the `-Werror` option is often a good thing to have (though I don't set it by default on my free software projects, because other people might use other compilers with different warnings, and I don't want to bloc…

> Indeed the `-Werror` option is often a good thing to have (though I don't set it by default on my free software projects, because other people might use other compilers with different warnings, and I don't want to block them outright). Another problem with C. There's way too much implementation-dependent behavior.

Not with Monocypher. That project has one implementation defined behaviour (right shifts of negative integers), and it's one where all platforms all behave exactly the same (they propagate the sign bit). In over 5 years, I haven't got a single report of a platform behaving differently (which would result in public key crypto not working at all).

However I do get spurious warnings, such as mixing arithmetic and bitwise operations even in cases where that's intended. Pleasing every compiler is not trivial.

Re: The case against a C alternative

#366

Earlier quoted context omitted.

> Last time you were looking at a binary using your editor or pager, how much better has your experience been thanks to NUL terminators? Not perceptibly better. And yeah, I do look at binary dumps now and then, after all, I wrote the code that generates ELF, OMF, MachO, and MSCOFF object file formats, and librarians for them :-)

I wrote simple ELF and PE/COFF writers too, but independently of that, zero terminators are what lets you find strings in a binary. And what allows the "strings" program to function. It simply couldn't work with without those terminators. Similarly, the text we're exchanging consists of words and sentences that are terminated using not zero bytes, but other terminators. I'm very happy that they're not length delineat…

> It simply couldn't work with without those terminators.

Yeah, it will. For a related example, I use `grep` all the time to find strings in source code. Source code is not 0 terminated. It works fine.

Re: The case against a C alternative

#367

Earlier quoted context omitted.

> memory allocation, and this is arguably orthogonal to the string representations A substringz cannot be produced from a stringz without doing an allocation. > you're free to make substrings using pointer + length or whatever, and this is in many cases the best solution Right, I can. And it's an ongoing nuisance in C to do so, because it doesn't have proper abstractions to build new types with. Even worse, if I swit…

> You wind up with two string representations in your code, and then what? Have each string function come in a pair? As said, I don't think this is the end of the world, and I'm likely to add a number of other string representations. While it happens rarely, I don't worry about formatting a temporary string for an API into a temporary before calling it. Because most "string" things are small and dispensable. Zero-ter…

> many length delineated APIs are designed to work with both - supply -1 as length, and you can happily put a string literal as argument, don't even have to macro your way with sizeof then to supply the right length.

I'm sorry, I just have to say "no thanks" to that. I don't really want each string function to test the length and run strlen if it isn't there.

By now, the D community has 20 years experience with length as part of the string type. Nobody wants to go back to the C way. It's probably the most unambiguously successful and undisputed feature of D. C code that gets converted to D gets scrubbed of the stringz code, and the result is cleaner and faster.

D still interfaces with C and C strings. The conversion is done as the last step before calling the C function. (There's a clever way to add a 0 that only rarely requires an allocation.) Any C strings returned get immediately converted with the slice idiom:

    string s = p[0 .. strlen(p)];
> I wouldn't like it if the APIs would miss the explicit length argument because there's a size field glued to the slice.

I bet you would like it! (Another problem with a separate length field is there's no obvious connection between it and the string - which is another source of bugs.)

Re: The case against a C alternative

#368
post #275

Earlier quoted context omitted.

There's nothing more complicated about using unique_ptr than a raw pointer, it just expresses who's responsible for calling `delete` explicitly in code rather than implicitly through program flow.

There's nothing complicated? You have to 1) #include 2) Write "std::unique_ptr foo" instead of just "My_Foo_Type *foo" in every definition. 3) Are required to define My_Foo_Type as a class with a separate deleter, or provide a deleter template argument at each declaration. 4a) write "foo.get()" in various places instead of just "foo". or 4b) lend around the unique_ptr in various places, breaking modularization and in…

> Data schemas and physical layout on the one hand, and memory and lifetime management on the other hand

How are they separate? Like, that’s what Rust does pretty explicitly, with great results.

Re: The case against a C alternative

#369

Earlier quoted context omitted.

C has a huge performance burden from 0 terminated strings. Programs are constantly running strlen() or equivalent to get the length. Length-delineated strings, like what D has, are an order of magnitude faster.

_There are_ programs that are constantly running strlen(). C strings are the default builtin string representation that has an acceptable tradeoff for performance vs space and simplicity for where they are used: Mostly in string literals, which are expected to be small strings. Mostly for printf() and friends. Zero-terminated strings are space efficient and don't allow bike shedding like length-prefixed strings do. A…

Zero-terminated strings was a bad decision even back then, let alone now. They make vectorization very painful, and you just needlessly have to iterate over strings at every use-site.

Re: The case against a C alternative

#370

Earlier quoted context omitted.

I wrote simple ELF and PE/COFF writers too, but independently of that, zero terminators are what lets you find strings in a binary. And what allows the "strings" program to function. It simply couldn't work with without those terminators. Similarly, the text we're exchanging consists of words and sentences that are terminated using not zero bytes, but other terminators. I'm very happy that they're not length delineat…

> It simply couldn't work with without those terminators. Yeah, it will. For a related example, I use `grep` all the time to find strings in source code. Source code is not 0 terminated. It works fine.

I use "grep -w foo" (or something like "grep '\'"), because when I look for "foo" I don't want "bazfoobar". grep -w only works because the end of words is signaled in-band (surrounding / terminating words with whitespace).
Post reply on HN