My favourite C string function is snprintf:<p>• It takes a buffer size and truncates the output to the buffer size if it's too large.<p>• The buffer size includes the null terminator, so the simplest pattern of snprintf(buf, sizeof(buf), …) is correct.<p>• It always null-terminates the output for you, even if truncated.<p>• By providing NULL as the buffer argument, it will tell you the buffer size you need if you want to dynamically allocate.<p>And of course, it can safely copy strings:<p><pre><code> snprintf(dst_buf, sizeof(dst_buf), "%s", src_str);
</code></pre>
Including non-null-terminated ones:<p><pre><code> snprintf(dst_buf, sizeof(dst_buf), "%.*s", (int)src_str_len, src_str_data);
</code></pre>
And it's standard and portable, unlike e.g. strlcpy. It's one of the best C99 additions.
It's too bad that many of the string handling functions in the C standard library are ticking time bombs. I like the approach taken in e.g. git which converts problematic function calls into compile errors <a href="https://github.com/git/git/blob/master/banned.h" rel="nofollow">https://github.com/git/git/blob/master/banned.h</a>
When I used C for a serious project, I always used `snprintf(dst, sizeof(dst), "%s", src);` to copy a string. It might be a little bit slow, but it freed me from all the headaches of identifying different string functions of C and remembering their subtle differences. It also is useful for other purposes, e.g. prefixing a string.
C2X will be adding memccpy() (note two c's in the middle, not memcpy!). Overview and justification at <a href="https://developers.redhat.com/blog/2019/08/12/efficient-string-copying-and-concatenation-in-c" rel="nofollow">https://developers.redhat.com/blog/2019/08/12/efficient-stri...</a>
Not sure I agree with the recommendation against strlcpy. While it is technically true that if you can't replace strcpy with memcpy you're using strcpy wrong, it's also true that most uses of strcpy are wrong, which I think is a better point to make. The stated purpose of strcpy is to copy a string, and if you're copying a string your best bet is strlcpy. The article is worded in such a way that you'd walk away thinking "I should always use memcpy."
What's the standard practice these days in C to move strings with lengths around? I've been out of C for at least a couple of years now, but I can't imagine it's changed in that time.
Related: Designing a Better strcpy, from last month[0]<p>[0] <a href="https://news.ycombinator.com/item?id=27537900" rel="nofollow">https://news.ycombinator.com/item?id=27537900</a>
I found the article kind of misleading: using memcpy for c-string is generally a bad idea, unless string length is bound with string buffer like std::string. Otherwise it will make code review very difficult.<p>In our team c-string is prefixed with sz_, e.g. char sz_name[13], and we always use a safe subset(or a safe replacement) of strxxx functions with these sz_ prefixed variables. Using memxxx with sz_ variables is explicitly forbidden, since it may break the NULL-terminating contract.<p>The sz_ prefix convention is by no ways like the hungarian naming nonsense. Suppose that you have "char sz_name[13]" in a structure of configuration parameters, sz_ tells the guy changing the field to keep it NULL-terminated, if they don't, it's their fault. On the other side, users of this field can safely use printf("%s", sz_name) without the risk of crashing the program.<p>For safe replacements of strcpy, I recommend:
<a href="https://news.ycombinator.com/item?id=27537900" rel="nofollow">https://news.ycombinator.com/item?id=27537900</a>
MSVC is a very curious choice of strcpy_s implementation given that MSVC is openly not compliant with C11, much less Annex K.<p>OpenWatcom, which implements a late draft of the standard behaves as expected on their testcase:<p><pre><code> Runtime-constraint violation: strcpy_s, s1max > RSIZE_MAX.
ABNORMAL TERMINATION
</code></pre>
The reason not to use the _s versions isn't that they are bad, it's that basically nobody has implemented them (hence me having to use Open Watcom to demonstrate this example)<p>[edit]<p>Just noticed that in the page they linked to at the top when they mention strcpy_s, it notes that the MSVC implementation predates even the original draft of the standard and lacks RSIZE_MAX.
If this is the case, why aren’t the stdlib functions defined this way? In all of the history of the longest-lived production language family besides FORTRAN, this blog post is the first voice to point out that memcpy should be the same operation as strcpy for null-terminated strings? What is going on here?<p>(Rust crowd snickers as they unwrap<‘jk> &mut *foo_buf)
Know what's even worse than strcpy?<p>strlcpy.<p>Every use of it I have seen was subtly incorrect. To use it correctly takes more code than anybody wants to write, or (AFAICT) ever does.<p>strcat is worse than both, though.
Not just strcpy either. Pretty much all str* functions are bad and should be replaced with their mem* equivalents when available.<p>I don't even know why the str* functions exist. They're just worse versions of mem* functions.
God the C runtime library is so bad. So is the C++ STL.<p>I think it’s a travesty that these languages defined an API but didn’t provide an implementation. Hindsight is 20/20, but what a nightmare!<p>It is far more rational to provide an implementation using standard language features. It’s not like strcpy needs to make a syscall!