4 ms·
I just don't understand why C hasn't been blessed with a proper string type yet. Object Pascal has had one (actually, several) for decades now and it doesn't h
by TimJYoung 8y ago
I just don't understand why C hasn't been blessed with a proper string type yet. Object Pascal has had one (actually, several) for decades now and it doesn't hinder the language's ability to handle low-level memory manipulation (you can still manually copy string memory, convert them back/forth into raw Char pointers, etc.), and generally serves to make string handling much, much safer for most applications. It does however, result in slightly more memory consumption for the length/reference count tags and does incur some overhead in the form of compiler-generated reference count checks at the end of functions. But, IMO, the advantages outweigh the disadvantages for general-purpose C programming and you're always free to fall back to the more manual methods of handling character arrays.
So, am I missing something and there is some concrete reason why this can't be implemented ?
- vortico 8y agoThere are many object oriented string types for C in various independent GitHub repositories, but they're not really interesting for C programmers because they enjoy the simplicity of null-terminated strings and moving data around with `for` loops.
- TimJYoung 8y agoI understand that (one of my favorite books on my shelf is "C Interfaces and Implementations" that shows some of the cool stuff that you can do with any C implementation, including "proper" strings), but they're not something supported in the compiler, which is, unless I'm mistaken, necessary for the reference count checks. My point is that implementing a new string type has zero effect upon existing C programs if they don't use the new string type, so I'm confused as to why it hasn't been done. If a C developer doesn't want to use them, then "no harm, no foul".
- vortico 8y agoWell, then you have two string types. The language will instantly become complicated as we indecisively choose between two different string types each function in our APIs. I see no harm in adding more functions around the string type we already have, but as I mentioned in https://news.ycombinator.com/item?id=17248446 https://news.ycombinator.com/item?id=17248446, `snprintf` is the mother-of-all-string-functions that does everything you need, so not much else is needed.
- TimJYoung 8y agoI would argue that you still have one string type, while the traditional C "string" type is actually an array of characters, or a pointer to an array of characters. :-) Re: snprintf - yes I saw that and it definitely does do most of the heavy lifting, but it still is something that the developer needs to handle manually (I know, I know, not everyone should be using C...).
- vortico 8y agoNo, char* is definitely a string type. By having another one, that would be two. Believe me, working with C and C++ code and converting back and forth between std::string and char* is a nightmare. Let's not design that into the language itself.
- TimJYoung 8y agoIn C++, can't you just get a reference to the first character in the std::string and use it like a C-style string ?
- jcranmer 8y agostd::string isn't null-terminated. You need to use .c_str(), which allocates a copy that is destroyed when the string is changed (or is destructed).
- TimJYoung 8y agoAhh, yes, forgot about that - thanks !
- thestoicattack 8y agoIt seems[1] that since C++11 .data() and .c_str() are the same function. c_str() is also documented as having constant complexity. If it made a copy, wouldn't it have to be linear? [1] https://en.cppreference.com/w/cpp/string/basic_string/data https://en.cppreference.com/w/cpp/string/basic_string/data
- staticassertion 8y agoHow often does C add things like this in general? I want to say... basically never? You're free to roll your own String type that has the length. No clue why people don't just do that though (I assume many do, but obviously a ton do not).
- blub 8y agoC doesn't really support properly encapsulated user-defined types, so yes, one can create their own String type but it will still be a pain to use and error-prone. One example is the stretchy buffer library that I saw posted recently here.
- TimJYoung 8y ago:-) You're certainly right here, but given that everyone thought that C was "going to be sent to the farm" a while ago and that shows zero signs of being true any time soon, it might be in the best interest of everyone to add such improvements, as long as they don't affect any existing C code. As I stated in my other reply, the only issue that I can see with rolling one's own String type is the handling of the reference counting for implicit deallocation.
- pjmlp 8y agoWe cannot send C to the farm and keep UNIX like OSes around, due to their symbiotic relationship. I really would like that something like SafeC or CheckedC would win the hearts of C devs
- scruple 8y ago> given that everyone thought that C was "going to be sent to the farm" a while ago For certain definitions of "everyone," maybe... I am no longer primarily a C programmer, and haven't been since around the end of 2013, and I'm still firmly in the "C isn't going any where" camp. I just happen to liken this stance to reality.
- TimJYoung 8y agoJust to clarify, I am definitely also not in the camp that thought that C was going away, rather that my general feeling is that most developers are afraid of it because of issues like this, and more sane semantics regarding one of the more widely-used aspects of any language would allow for greater adoption while not sacrificing reliability or backwards-compatibility. IOW, I think it would be a win-win.
- CodesInChaos 8y agoA built in slice type (i.e. a (pointer, length) tuple) would prevent many of the issues with C strings without departing so far from the language design. If done from the beginning, slices could have gotten the `T[]` syntax and array-pointer decay could have been replaced by the easier to use and safer array-slice decay. But of course backwards compatibility prevents this now.
- wahern 8y agoBackwards compatibility doesn't prevent adding a slice type with specialized syntax. The stumbling block is 1) defining sane semantics agreeable to a majority of people and 2) implementing it in a major implementation. I hold out hope it'll happen, but I'm probably in denial. The fact that VLA function parameters were made optional in C11 doesn't bode well, but perhaps that's because it's incomplete--syntax and semantics stops short of what's needed to spur adoption of safer APIs. With a proper slice construct that was easy to use and integrate into idiomatic C code then there'd be more demand for implementing and using the necessary VLA compiler machinery, if not VLAs themselves.
- munificent 8y agoI think it's mostly a switching cost problem. Strings-as-char-* are part of the public APIs of damn near every C library, including the standard library, so there's no way to change that idiom without breaking the world or causing a huge migration tax. The kind of people using C are often doing so specifically because they want to avoid that kind of churn and want a maximally-stable platform, even if what it's stabilized to is sub-optimal.
- TimJYoung 8y agoYes, but none of that would need to change. I hate to keep harping on Object Pascal, but it really is a nice implementation: in OP, you can pass a string to a C API, such as the Windows APIs, like this: Result:=CreateFile(pChar(FileName), AccessMode,ShareMode,nil, OpenFlags,AttrFlags,0); where FileName is a String and pChar is the more traditional C-style pointer to an array of characters. The compiler will prevent you from passing a Unicode/Wide string to an API call that expects an ANSI string pointer, or vice-versa. So, interop with the system-level APIs of Windows or Linux is seamless and easy.
- TimJYoung 8y agoBTW, I almost forgot to mention: the String type in Object Pascal implicitly contains a NULL terminator, so the above call is zero-copy. More information: http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Internal_Data_Formats_(Delphi) http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Internal_D... under "Long String Types".
- pjmlp 8y agoEasy, see how Go devs are reluctant to adopt features from other modern languages? Travel back in time, when they were busy implementing C. Compare how ESPOL, NEWP, PL/I, PL/S, PL/X, PL.8, BLISS, Algol 68 implemented arrays, strings and unsafe code blocks, and how C decided to go their own way. BCPL was originally designed as means to Bootstrap CPL, not to be used alone. See a pattern there? Then AT&T could not sell UNIX, gave it away at a symbolic price of about $100 and the rest is history.