The talking point is a string type that can be used with some convenience. Let's say join multiple of them together at runtime with '+'. Or whatever, maybe just a function call. I was explaining why it doesn't work just like that.
The str type you mention is a nice feature, and in the future when I will have switched to Rust or whatever, I might use it to write my programs in 5 lines less.
While in C I have to use C's "slice" type: char x[] = "Hello". I know it's not quite as good since if I was to pass this around, I would have to make a pointer + length representation for this. If I needed it, it can be automatized from string literals: struct String(const char *buffer, size_t size); #define STRING(lit) (String){lit "", sizeof lit - 1}.
Or char buffer[256]; my_api(buffer, sizeof buffer);
For the few situtations where string manipulation is required, it's just not a real problem.
Strings are so tiny an abstraction over plain memory that every C programmer ends up doing them their own way. And that can be a good thing. I already proposed a couple of ways to represent or muck with strings in my other comment.
I 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)
The standard C functions are enough of a mess mentally for me that I try to use them only for simple things.
If I'm dealing with lots of string manipulations I usually create a struct with a count and an alloc size and a char* pointer and write init, cleanup, extend, and append functions specific for it and use that as a string type. It's less of a mental load for me to deal with reallocating an array and keeping count and alloc updated correctly once than it is knowing that character arrays are being recounted all the time and worrying about exactly where the '\0' is going to end up and if my buffer is large enough for every string I'm dealing with.
I for one like "raw char arrays", and really don't care about missing string functionality in C. I basically use sizeof, snprintf, memcpy and am just fine. I've toyed with defining struct String{ptr,size} sometimes but largely it just gets in the way.
If you think it's necessary, it's very easy to make an argument that you'd have to have a generic type for slices of any type. (Actually, more so than strings, since C is just not a language for domains with a focus on strings).
Now, whether you think a language must have a generic slice type or not, C is simply not the language where you can fit that in.
I wish C had gone back and done a better implementation of strings that wasn't null terminated. Or at least an implementation of plain buffers with a richer libc for manipulating them.
I know you can find bolt ons, but they aren't terribly useful since no 3rd party libraries use them. You have to resort to stuff like antirez's sds.
Yes, that's why I'd make my own string type. But it always turned out to be more trouble than it was worth, because every other piece of C code wanted to use 0 terminated strings.
C had the opportunity to include this but they did not. It is my understanding that they wanted to design everything in C as inherent to the language, rather than magic types, especially a struct. There is an elegance in the notion that a string is just an array of characters. If I’m working with a significant amount of strings in C, I can keep track of lengths, not a huge deal.
Wow, that sounds nightmarish. Three different ways to store the string, pointers to buffers everywhere, and because it is so complex your string library needs to account for all possibilities because there's no way anybody is going to want to manually twiddle with those strings.
If you get it right and hide all of the complexity from the user then it's not quite as bad, although undoubtedly confusing the first few times someone inspects it in their debugger.
Not having first class "strings" (which are a cloudy concept) is exactly the right call for a systems programming language that is concerned with the harder truth about in-memory structures.
If you want to "join together" strings data and printf/snprintf isn't convenient enough, go ahead and use different tool. But don't act like computers can natively compute the concatenation of two string buffers, and offer you the result into your expecting hands. On a lower level, everything needs to be stored in memory somewhere, and if "just somewhere in a heap allocation" is good enough for your purposes, use a different language but don't expect best performance nor simplicity.
Yeah, because of NUL-terminated strings. They cause so many problems it's not even funny. Even something simple like computing the length of the string is a linear time operation that risks overflowing the buffer. People attempted to fix these problems by creating variations of those functions with added length parameters, thereby negating nearly all benefits of NUL-terminated strings.
Why can't we just have some nice structures instead?
All I/O functions should use structures like these. This alone would probably prevent an incredible amount of problems. Every high-level language implements strings like this under the hood. Only reason C can't do it is the enormous amount of legacy code already in existence...
Tbf, anything but bytes is a cloudy concept and not accepting that is just making things harder for yourself for literally no reason. If you have native arrays, you can have native strings, end of discussion.
C doesn't have strings is because there wasn't a well accepted library for them at the precambrian time it was being designed. Otherwise it would've, not out of some ideological fit-for-purpose nonsense. It was supposed to be a high level language, as high as they could go with systems being as crap as they were back then.
Obviously, a struct is one option. The problem is that you then need to make a whole string library. Thankfully, many exist, so this is a non issue, unless there's a requirement that you write all the code yourself.
reply