Well, this is not very helpful advice, because strncpy(a, b, sizeof(a)) is in no way more safe than strncpy(a, b, sizeof(a)-1), because the latter is not 0-terminated either. And from malloc(), as in the examples, comes no 0-termined buffer, but random garbage memory. What would be safer is to alway 0-terminate the buffer after copying, and using the simplest copy possible:<p><pre><code> strcpy(a, b, sizeof(a));
a[sizeof(a)-1] = 0;
</code></pre>
But this is more boilerplate and hence more error-prone.<p>Even safer, use strlcpy() (if available) or snprintf() which both 0-terminate (except under Windows, maybe). (But beware when preparing something for copying from trusted to untrusted: strncpy() clears the rest of the buffer while strlcpy() and snprintf() do not, so you might leak info via uninitialised memory behind the end of the string if you copy out that buffer across a trust boundary. Actually, the authors 'sizeof()-1' solution is less secure in this context.) So, use:<p><pre><code> snprintf(a, sizeof(a), "%s", b);
</code></pre>
And don't tell me anything about speed, please. Your main concern with C is not micro optimisations but robustness and avoiding undefined behaviour (and that snprintf() is not too slow).<p>And for multiple concats, use multiple snprintfs(), like so:<p><pre><code> char *i = a, *e = a + sizeof(a);
i += snprintf(i, e-i, "%s", b1);
i += snprintf(i, e-i, "%s", b2);
i += snprintf(i, e-i, "%s", b3);
</code></pre>
This is the most concise way I know to write this that works without buffer overflow (your main enemy, even more vile than missing 0-termination), without thinking too much, without writing too much boilerplate, and that is relatively robust against breaking in code restructuring (like, appending more stuff in the middle). The idiom also resembles a bit old style C++ iterators ('i' and 'e').<p>Oh, and a truncated string is usually not good anyway, be it 0-terminated or not. So you do need to check for that after all that stringing stuff:<p><pre><code> if (strnlen(a, sizeof(a)) >= sizeof(a)-1) {
/* ... error ... */
}
</code></pre>
Don't miss that '-1' there. Off-by-one is another enemy to know well. And dispite that check handling missing 0-termination, do not be tempted to fall back to strcpy(), because missing 0-termination is bad(tm).<p>Phew!<p>C is bad with strings. The above resembles C++ iterators ('i' and 'e') and works fine with any good snprintf implementation (i.e., probably not under Windows).<p>And do not copy structs with memcpy, just assign them! memcpy() is for arrays only. This is not going to go away, is it?