7 ms·
C String Creation
- jws 11y agoGood news in the article, apparently asprintf is scheduled for the next POSIX standard. I wonder how one sees what is in the next POSIX standard, it would inform my choices of what I use. I'll use something that works on all my platforms if it is headed to a standard, but usually not if it may head to oblivion. Also open_memstream is POSIX 2008, now if it would just get into OS X…
- audidude 11y agoIf you want this today on all (C89) platforms, GLib ships an embedded copy of gnulib and runs virtually everywhere.
- sortie 11y agognulib is atrocious beyond belief though. I hear GLib tends to abort your process on OOM, though I haven't done my research on this library, so I would be careful using these to develop reliable software.
- generic_user 11y agoThese functions are proposed for the next C standard. They are in part 2 of the bounds checking interface. The relevant proposal is n1337 'dynamic allocation functions' asprintf() aswprintf() vaswprintf() fmemopen() open_memstream() open_wmemstream()
- jhallenworld 11y agoShould we not be using wchar_t strings in modern C? int main(int argc, char *argv[]) { wchar_t buf[100]; wprintf(L"Hello, world!\ntype something>"); if (fgetws(buf, 100, stdin)) wprintf(L"You typed '%ls'\n", buf); if (argv[1]) { char *s = argv[1]; /* Convert char string to wchar_t string */ size_t len = mbsrtowcs(buf, &s, 99, NULL); if (len != (size_t)-1) { buf[len] = 0; wprintf(L"argv[1] is '%ls'\n", buf); } return 0; } It's a pain, but the advantage is access to iswalpha() and friends.
- hthh 11y agoOn Windows, sure. On other platforms UTF-8 is generally preferable (in my opinion).
- jhallenworld 11y agoAnnoyingly, there is no simple user accessible UTF-8 decoder in libc. The only standard way to use iswalpha is to convert to wchar_t first. One hack is to assume that bytes of UTF-8 encoded strings above 127 are all letters. It mostly works :-)
- akira2501 11y ago> Annoyingly, there is no simple user accessible UTF-8 decoder in libc. Am I misunderstanding you, because I've always thought that's what the mbtowc(3) family of functions was?
- jhallenworld 11y agoWell you are right, but these functions are not terribly fun to use. Consider a parsing function which extracts an identifier. For ASCII it's: if (isalpha(*s)) { *d++ = *s++; while (isalnum(*s)) *d++ = *s++; } To use UTF-8 / Unicode should require only small changes: if (iswalpha(decode(&s)) { encode(&d, advance(&s)); while (iswalnum(decode(&s)) encode(&d, advance(&s)); } For efficiency, don't decode twice- have the decoder return a pointer to the next sequence: if (iswalpha(c = utf8(&s, &n))) { encode(&d, c); s = n; while (iswalnum(c = utf8(&s, &n))) { encode(&d, c); s = n; } } Also should be able to match a string in line: if ('A' == utf8(&s, &t) && 'B' == utf8(&t, &s) && 'C' == utf8(&s, &t)) // we have 'ABC'.
- sortie 11y agombtowc isn't necessarily thread safe, it's better to recommend mbrtowc.
- 11y ago
- hthh 11y agoThis is an interesting article, but the "Portability" comments could be a lot more useful: strndup and open_memstream are both "POSIX 2008", but strndup can be used on OS X while open_memstream cannot.
- apaprocki 11y agoWhile not immediately clear, OS X is POSIX 2003. So if you go strictly by POSIX standards, you shouldn't rely on either.
- to3m 11y agoYou'd probably be able to duplicate open_memstream on OS X using funopen.
- btrask 11y agoRan into this recently. It's not open_memstream but same idea: https://github.com/NimbusKit/memorymapping https://github.com/NimbusKit/memorymapping
- sortie 11y agoI deliberately didn't write that to avoid the page going stale when OS X adds it. But OS X is behind the times and that's harmful. POSIX 2008 has been out for years and most of the lacking features are trivial to add. They're being actively harmful to Unix software by not having modern interfaces, forcing portable software to be worse. The purpose of the article is to highlight the interfaces, and when they're suited, rather than being a replacement for your system manual page or a portability guide. Since OS X isn't a free software Unix (though its libc is), I don't really consider it among the relevant modern Unix systems. Linux, the BSDs, and so on all have the POSIX 2008 features mentioned here.
- kevin_thibedeau 11y agoI see too much damage caused by strncpy() to ever recommend it for use. Code that is blissfully unaware of the non-guaranteed NUL or that repetitively does extra work to guarantee a NUL. Use strlcpy() if available or reimplement it.
- sortie 11y agoAs in the article, strncpy has valid uses, but it's widely misunderstood due to the poor name. strlcpy is what the name suggests. People are also surprised by the zero padding.
- rumcajz 11y agoThis is an advice to use C in a way that resembles higher level languages. But it you want to do so, why not simply use a higher level language? The power of C -- which distinguishes it from most other languages -- is the ability to allocate almost everything statically. In fact, the older I get the more I appreciate pre-Algol60 way to allocating stack frames statically.
- sortie 11y agoWhether C is appropriate is highly depending on the project and context. Higher level languages offer a lot and should be used when appropriate. But when C is appropriate, and these problems arise, which they will in any C codebase of appreciable complexity, these string creation interfaces are waiting for you, and will help you write correct code. It's usually a worthwhile effort to reconstruct higher level abstractions in C, in a good manner, for the same reasons you use them in higher level languages. Note that statically allocating everything is hardly always possible. See the distinction between bounded and unbounded in the article, the unbounded case is really common.