3 ms·
Okay, I agree that by default, C strings are bad. But it doesn't have to stay that way. Someone else in the comments mentioned antirez's sds library for dynami
by gavinhoward 4y ago
Okay, I agree that by default, C strings are bad.
But it doesn't have to stay that way. Someone else in the comments mentioned antirez's sds library for dynamic strings. This works, but you could also easily roll your own. All you need is an init function, and perhaps an assert or other check at the end of it that the string has a nul terminator.
At that point, type checking will let you blindly pass those strings (or their char arrays) to any of those C functions without worry.
Edit: I'll also add that I think a string library should have a difference between static strings and string builders (dynamic strings). It makes everything easier.
- magicalhippo 4y ago> by default, C strings are bad. C strings aren't bad. They can't be, because they don't exist. C doesn't have strings. And that is the issue. As you say, things get a lot better when you actually introduce strings as a concrete concept rather than a set of lose conventions.
- junon 4y agoThere is no "loose convention". A C string is a null terminated string of non-null bytes. That's the definition. Working with them in memory-unconstrained environments is unnecessarily hard.
- magicalhippo 4y agoThere is indeed just convention. The language defines string constants similar to what you say[1] (an array of characters, terminated by a null character), but in the language itself there's no way to declare that a function takes a string rather than a pointer to a character. Alternatively if you work with a fixed-sized character array, there's nothing separating it from "just" an array of characters that are not null terminated. So that strcmp expects a string rather than a pointer to a character is just convention. In languages which actually has strings as a concrete concept, like say Pascal and derivatives, you can actually differentiate between those two cases. [1]: https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#String-Constants https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#...
- int_19h 4y agoThat means that the strings aren't properly reflected in the type system. But the existence of string literals with a very definite in-memory layout means that it's not just a convention even so.
- magicalhippo 4y agoBut you can't use those string literals in any way without relying on convention.
- int_19h 4y agoThat was my point. Although you can, actually - since literals themselves are array-typed, you can sizeof them to get the character count without relying on null termination. It's even possible to get a non-null-terminated literal if the target array type is not large enough to fit null, e.g.: char s[3] = "foo"; // not null-terminated!
- giantrobot 4y ago> character count Byte count.
- int_19h 4y agoIf you want to be pedantic, "an object declared as type char is large enough to store any member of the basic execution character set". It doesn't actually have to be a byte. In practice, in C context, character == char == byte. Other concepts have to use different names to avoid confusion with the language spec.
- junon 4y agoIn C a 'char' is a 'byte', if we're going to be extra pedantic.
- flohofwoe 4y ago> C doesn't have strings. C has string literals though, and those bake a specific string representation into the language (of course libraries can use their own string representation, but those then need at least some conversion function from string literals).
- b5n 4y agoString literals in C are simply a pointer to an array of bytes (generally speaking), and that's how they should be treated. Considering them as strings in the HLL sense is the entire issue here.
- tialaramex 4y agoI don't think it's useful to pretend C doesn't have strings when it has string literals. WUFFS doesn't have strings. That's what a language which doesn't have strings looks like, you can't write "Hello, world" in WUFFS because it involves Strings, which WUFFS doesn't have, and I/O, which WUFFS also doesn't have. A pretence that C doesn't have strings because it lacks a concrete string type in the language itself also seems like you'd be claiming C++ doesn't have strings, Zig doesn't have strings, and Rust came pretty close to not having strings (for a while it was mooted to make Rust's str just a slice [u8] but today Rust does bless str as a distinct type even though e.g. &str and &[u8] aren't very different)
- magicalhippo 4y agoC++ before C++11 didn't. I've fixed errors in projects which was due to string literals not being std::string. After C++11 things are more murky due to user literals[1]. I'd lean towards saying the language still doesn't, but yeah, murky. Zig and Rust I don't know enough about. And I'm not pretending. C has string literals which are of a non-distinct type. You can't distinguish between a string literal and an array of characters. This is the crucial bit. The result is that the standard library, and lots of other code, relies on convention alone to pass strings around. This has been and continues to be the source for countless serious bugs. The kind of bugs which are a total non-issue in languages which has strings. [1]: https://en.cppreference.com/w/cpp/language/user_literal https://en.cppreference.com/w/cpp/language/user_literal
- junon 4y agoThere's also RapidString, though the original author seems to have disappeared off of the internet. Would be curious to see benchmarks against sds.
- bluetomcat 4y agoThe best way to write C is to treat strings as memory locations with characters and nothing more. Every such memory location has an allocated size, either statically at compile-time (with literals and arrays), or dynamically with malloc and friends. Treat string operations as mere memory operations and don't imagine them to be something else. The str* functions from the standard library are just convenience helpers which are not adding "string" functionality whatsoever.
- nerdponx 4y agoMaybe you could summarize this by saying that C strings are "strings of bytes", not "strings of characters".
- lolcatuser 4y agoIt's better to say that, in C, characters are bytes. That's why coming at this from the modern perspective of "characters are the things on my screen" is always going to confuse you - C doesn't have bytes, only characters. C programmers (should) understand this the same way Lisp programmers understand that "CAR" and "CDR" refer to "first" and "rest" or Forth programmers understand that "the stack" is the data stack and has no relation to the call stack.
- nerdponx 4y agoSo a "char" is a byte, but a "char" is perhaps not a "character", except as a funny coincidence of jargon.