Earlier quoted context omitted.
Well no, and if we're being pedantic I didn't imply that.
> ...concatenating them with a plus sign, like you do in scripting languages.
The case against a C alternative
321–330 of 388 posts
Re: The case against a C alternative
#322Earlier quoted context omitted.
The real overhead is not safety code but inefficient design and unnecessary (and often detrimental to the user) features. The added 10% of safety checks is nothing compared to orders of magnitude of bloat modern software has. Moreover, a lot of C codebases have the same safety checks manually implemented into them, sacrificing performance in order to have less bugs. And when it comes to designing a modern C alternati…
I'm suspicious that people arguing that safety checks making things slow are basing that on the very stale now idea that CPU's work sequentially. Which isn't true for super scalar machines at all. And also forgetting compilers will optimize away a lot of them. There is an asymmetrical risk here. On one hand the compile might emit checks that aren't needed. On the other that the programmer will fail to insert a check…
Re: The case against a C alternative
#323Earlier quoted context omitted.
_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…
> that has an acceptable tradeoff for performance vs space and simplicity for where they are used Is it? I've been programming strings for 45 years now. Including on 8 and 10 bit machines. All that space efficiency goes out the window when one wants a subset of a string that isn't a common tail. The simplicity goes out the window as soon as you want a substring that isn't a common tail. Now you have memory allocation…
No, I recommend everyone to use whatever fits the situation best. It might be a 2 byte start index and a 1 byte length fields that expresses the length as a multiple of 12 bytes. It might be rope data structure. Or it might be whatever. "String" is not a super well defined thing, and I don't understand why everybody is so super concerned about a canonical string data type. String data types are for scripting languages. 99% of my usage of string (literals) is just printf and opening files, and C does these just fine.
Zero terminated strings are only a default thing for string literals that does indeed bring a little bit of simplicity and convenience (no need for a builtin string type and the associated bike shedding, and only need to pass a single pointer to functions like printf).
> Meaning they become length-delineated programs, except it's done manually, tediously, and error-prone.
Not sure when is the last time I found it "manually, tediously, and error-prone". There are very rare cases where I have to construct zero-terminated strings from code, or need to strlen() something because of an API. And even when these cases occur they don't bother me at all. Stuff just works for me generally and I'm moving on. I have probably 500 stupid bugs unrelated to string handling before I once forget a zero terminator, and when that one time happens I just fix it and move on. On the plus side, given that we're in C where there are no slice types, zero-terminated strings spare me to pass extra length values for format strings or filepaths.
Sometimes I envision being able to use slices but I have some concerns if that would be an actual improvement. Importantly it should be about arrays and not just about strings. Strings are arrays, they aren't special.
I think a good design for slices could be one whose length can never be accessed by the programmer, but which can be used for automated bounds checks. Keeping size/capacity/offset and 43 cursors into whatever buffers separate is actually correct in my view from a modularization standpoint, because "String Index/Size/Offset etc." isn't a 1:1 relationship.
> Whenever I review C code, the first thing I look at are the strlen/strncpy/str* sequences. It's almost always got a bug in it, an off-by-one error.
You will have to look quite a bit to find strlen() or strncpy() in my code. I'm not advocating for them, and not advocating to build serious string processing on top of zero-terminated strings.
Re: The case against a C alternative
#324Earlier quoted context omitted.
I also like this priority in Rust, which constantly makes me wonder why the developers allowed shadowing. It has already caused runtime bugs for me while the compiler didn't even throw a warning about it, and as Rust is otherwise so strict about making possible mistakes like this explicit it's definitely not the first cause I consider when debugging.
While I think shadowing is great for code readability and I've never encountered a bug caused by it, you can always make sure clippy doesn't let you do it by putting a `#![deny(clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated)]` at the top level of your crate.
let geese = something(lots_of_birds).bunch().of_chained().functions();
let geese = geese.somehow().just().count_them(); // We don't actually need geese, just #
Could you name that first variable something else? Yeah. But, it's geese, it's not the number of geese, it's a different type, but it is just geese, that's the right name for it. OK, maybe rename the second variable? But number_of_geese is a stupid variable name, I would push back on a patch which tried to name a variable that because it's stupid. n_geese isn't stupid, but it is ugly and Rust is OK with me just naming it geese, so, geese it is.However, if you do run into trouble those Clippy rules can save you. You probably will find you don't want them all (or perhaps any of them) at deny, but Rust is content for you to decide you only want a warning (which you can then suppress where appropriate) and importantly these are three rules, you might well decide you only hate shadow_same or shadow_reuse or something. Here's the link specifically for shadow_reuse as an example:
https://rust-lang.github.io/rust-clippy/master/#shadow_reuse
Re: The case against a C alternative
#325Earlier quoted context omitted.
Babylonians used it. That's the origin of our time counting system of hours, minutes and seconds and our angle measuring system of degrees, minutes and seconds. Anyway, if we someday change our number system away from 10, I hope the change will be towards a smaller base, like 8 or 6, because when one is a child, it sucks to learn the times tables. Base 12 would increase the number of entries by 44%. Base 8 would decr…
That's not a pure number system though, because it didn't have a separate character for each digit
Re: The case against a C alternative
#326Earlier quoted context omitted.
unique_ptr is pretty bad for performance as well. It is more complicated to use compared to raw pointers and encourages an OOP object-per-object piecemal code and data architecture. I've never seen a C++ program making use of unique_ptr that didn't give a strong smell of enterprise programming.
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.
Sometimes you C++ guys are just blinded by the tale of "zero-cost abstractions".
unique_ptr, like the idea of RAII in general, binds together what should be separate. Data schemas and physical layout on the one hand, and memory and lifetime management on the other hand. What you get as a result is what you deserve: The idea of "more safe and maintainable" where the "more" isn't added to the equivalent non-RAII program. No, it is added to the more convoluted, less understandable, and thus inherently less safe and maintainable program. Who knows what the bottom line is (in my experience often safety is a bit better but I pray for you if you need to debug a problem, and maintainability is much worse), but out of interest in my own sanity I know my preference.
Re: The case against a C alternative
#327Earlier quoted context omitted.
What you're seeing is most likely not bugs (it is clang after all), but the result of the much stricter default compilation settings in "zig cc" which tends to break a lot of C code that hasn't been checked against a static analyzer or ASAN before.
No, they were bugs in zig CC. They were things like linking against the wrong frameworks on macOS.
Re: The case against a C alternative
#328Earlier 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…
Precisely. This is perhaps the strangest part of the original post: C++ has the same performance advantages as Rust! It has them not because it's more safe (although it is, in some regards), but because it allows programmers to express behaviors that the compiler can reason about statically.
And many that are negated due to a bad std API.
Re: The case against a C alternative
#329Earlier 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.
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.
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.
Re: The case against a C alternative
#330(5) is pretty irrelevant, ABI isn't language. You can strap basically any language on top of the C ABI. Many contender languages either use it natively or offer low-cost/no-cost C ABI bindings, specifically as its the lingua franca ABI. You can check (5) off your list if your choice of replacement language has easy C ABI interop. [edit] (1) isn't particularly relevant either. These days the tooling for detecting memo…
Why is this down-voted? C does not have a standard ABI, this guy here is right?