The article misses a really big item. I’ve programmed in C for 20+ years and then recently switched to rust. When fellow C programmers ask me how Rust is going, I say “it’s modern” and “it’s consistent”. What I mean by that unlike C, Rust doesn’t have 50 years of baggage: string functions that handle null termination all differently, complicated implicit promotion rules, null-terminated strings that haven’t been a go…
The case against a C alternative
341–350 of 388 posts
Re: The case against a C alternative
#342Earlier quoted context omitted.
I haven't even suggested to roll your own "string" type. Not more than rolling any other type of array or slice. In my programs I normally do not define a "string" type. Not a central one at least. Zero-terminated strings work just fine for the quick printf() or fopen(). Instead, I might have many string-ish types. A type to hold strings in the UI (may include layout information!), a type of string slice that points…
Any length delineated string you're using, and you did say you were using length delineation, suffers from the problem of not being compatible with any other C code. There's a good reason operating system API calls tend to use 0 terminated strings. If you want to do a quick debug printf() on it, well, you could use %.*s, but it's awkward and ugly (I speak from lots of experience). Otherwise, you gotta append the zero…
I don't care about having to provide zero-terminated strings to OS and POSIX APIs, because somehow I almost always have the zero already. Maybe I'm a magician.
Sometimes I have not, but >99% of what I give to printf is actually "text", and that pretty much always has the zero anyway. It's a C convention, you might not like it, but I don't sweat it.
If I want to "print", or rather "write", something other than a zero-terminated string, which is normally "binary data", I use... fwrite() or something analogous.
> C ranks among the most inconvenient string processing languages
I've written my share of parser and interpreters (including also a dysfunctional toy compiler with x64 assembler backend, but doesn't matter here), so I'm not entirely a stranger to this game either.
I find parsing strings in C is extremely _easy_, and I find it in fact easier than say in Python where going through a stream of characters one-by-one feels surprisingly unpythonic.
Writing a robust, human-friendly parser with good error reporting and some nice recovery attributes is on the harder side, but that has nothing to do with C strings. A string input for the average parser isn't even required, you just read char by char, frankly I don't understand what you're doing that is hard about it. It doesn't matter one bit if there's a zero at the end or not.
Re: The case against a C alternative
#343Earlier quoted context omitted.
Not to mention that both C++ and Rust can specialise algorithms and containers for specific types, whereas in C most developers resort to void* and function pointers. It's not unusual to see C programs written in a "typical" C style become dramatically faster when rewritten in a more modern language. For example, typical C programs also don't use hashtables even when this makes the most sense, causing weird performan…
It's not unusual to see C programs written in a "typical" C style become dramatically faster when rewritten in a more modern language. This was equally true back when C vs Fortran was the big debate, and something not easily captured in benchmarks. C, as written by an expert in high performance C, was equally fast as Fortran written by an expert in high performance Fortran. C, as written by a domain expert with limit…
The gist, as I recall it was: the initial, idiomatic, written-for-maintainability version of the C# program was significantly faster than the C++ equivalent. Up until the end, the C# version also generally needed to go through less heroics to keep up with the C++ version. Eventually, the final C++ version did end up being faster than the fastest C# one, but, considering what needed to be done to get there, it was a decidedly Pyrrhic victory.
One huge mitigating factor, though, is that the model program was doing something business-y. I doubt C++ would have had such a hard time of it if it had been a number crunching or systems program.
Re: The case against a C alternative
#344I just want: C with: - bounds checking - use after free checks - modules - sane metaprograming/template - tagged union built in without: - macro - pre declaration - split header/source That's it, no borrow checker, no weird syntax, no nothing So far D is the answser for me, but i'm worried about its future, will they keep improve the language in that direction? or will they continue with their high level stuff Zig/Ja…
Have you looked at C3 (the language OP is making)? I think it hits a lot of your boxes.
Also no language server is a hard pass, tooling is important
Re: The case against a C alternative
#345Earlier quoted context omitted.
First, not all language safety features have to manifest themselves as run-time checks. A properly designed language will allow many safety checks to be done at compile-time. And second, would you really rather deal with security holes on an on-going basis? The problem with C is not that you can write unsafe code in it, it is that the design of the language -- and pointer aliasing in particular -- makes it impossible…
I'm not here to defend C, but to point out a problem that many advocates make when they cherry pick examples of how their language is both safer and more performant than C. Simply put, that example is irrelevant when the size of the array is not known at compile time. The moment that you have a dynamically allocated array, you are either dropping safety (e.g. expecting the developer to perform bounds checks when nece…
Especially when to get the compiler to do the right thing safely you need to add manual bounds checking with the expectation that the compiler will optimise it away, but without any mechanism to ensure that it actually happens.
It depends greatly on the problem at hand, but there are definitely cases where even with a dynamic array size we can unroll our loop such that we check bounds less than once per iteration.
Re: The case against a C alternative
#346Earlier quoted context omitted.
Warning is one thing, but crashing is better. That's possible to do in a C compiler too of course, because in this example the array hasn't decayed to a pointer and its size can be recovered. The issue is when you pass the array to another function, it can't track the size without changing the ABI.
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…
Rust's compiler will reject programs unless it can prove them to be valid. C compilers will accept programs unless they can prove them to be invalid. But then C warnings can lead to an indeterminate state: code that looks iffy may be rejected, but we've not necessarily proven that the code is wrong. We're still trusting the programmers' claim that code which may exhibit undefined behaviour with certain inputs won't ever receive those inputs.
Re: The case against a C alternative
#347Earlier quoted context omitted.
Warning is one thing, but crashing is better. That's possible to do in a C compiler too of course, because in this example the array hasn't decayed to a pointer and its size can be recovered. The issue is when you pass the array to another function, it can't track the size without changing the ABI.
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…
I don’t really love forcing errors; when a program is “under construction” you should be able to act like it is and not have to clean up all the incomplete parts. It also annoys people testing new compilers against your code.
Re: The case against a C alternative
#348Earlier quoted context omitted.
Any length delineated string you're using, and you did say you were using length delineation, suffers from the problem of not being compatible with any other C code. There's a good reason operating system API calls tend to use 0 terminated strings. If you want to do a quick debug printf() on it, well, you could use %.*s, but it's awkward and ugly (I speak from lots of experience). Otherwise, you gotta append the zero…
Sure, I know who you are but I hold opinions too :-) I don't care about having to provide zero-terminated strings to OS and POSIX APIs, because somehow I almost always have the zero already. Maybe I'm a magician. Sometimes I have not, but >99% of what I give to printf is actually "text", and that pretty much always has the zero anyway. It's a C convention, you might not like it, but I don't sweat it. If I want to "pr…
Re: The case against a C alternative
#349Earlier quoted context omitted.
Exactly! And because you can't create a substring without mutating the original value, you see that C code often needs to resort to unnecessary copying as well.
No. You can't create a zero-terminated substring other than a proper suffix or a buffer copy. But that's not really a surprise right? Well then, don't use zero-terminated strings for proper string processing. You don't have to use zero-termination, even when some programmers in the 70s and 80s were convinced enough of it that abominations like strtok() landed in the standard.
You can choose between zero-termination and having to convert strings back and forth when using idiomatic libraries.
Re: The case against a C alternative
#350Earlier quoted context omitted.
Warning is one thing, but crashing is better. That's possible to do in a C compiler too of course, because in this example the array hasn't decayed to a pointer and its size can be recovered. The issue is when you pass the array to another function, it can't track the size without changing the ABI.
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…
Another problem with C. There's way too much implementation-dependent behavior.