7 ms·
I think memccpy is an improvement, so I support it, but it's still complicated to use in practice. The article gives this example for a copy followed by concate
by dwheeler 7y ago
I think memccpy is an improvement, so I support it, but it's still complicated to use in practice. The article gives this example for a copy followed by concatenation:
char *p = memccpy (d, s1, '\0', dsize);
dsize -= (p - d - 1);
memccpy (p - 1, s2, '\0', dsize);
Notice that you have to recalculate dsize (correctly without one-off errors!), it assumes you have dsize itself, and this doesn't detect overruns (which in many cases you should do).
So real-world code would look more like this:
// dsize is the space *available* in d, including \0
size_t dsize = sizeof(d); // if d is an array
// ...
char *p = memccpy (d, s1, '\0', dsize);
dsize -= (p - d - 1);
if (dsize <= 0) goto overflow; // handle overflow
char *q = memccpy (p - 1, s2, '\0', dsize);
dsize -= (q - (p - 1) - 1);
if (dsize <= 0) goto overflow; // handle overflow
It's a little easier to understand than strncat/strncpy versions, it doesn't unnecessarily read its inputs past where they are needed like strlcat/strlcpy do, and it's more efficient than snprintf. So yes, it's an improvement and I support it. However, this is still rather complex; in particular, it's way harder to understand compared to code that uses snprintf, and certainly harder to understand than pretty much any other programming language higher level than assembly.
So let's accept this improvement, and keep striving to do better.
- imglorp 7y agoIf you want simple, it's hard to beat the original K&R (1978!) while(*p++ = *q++); which is what sold a generation on the whole idiom. Of course its time is long gone but useful to learn.
- dwheeler 7y agoThis construct: while(*p++ = *q++); is simple. But I agree with you, its time has long gone, because in many programs, this code is also wrong. This idiom assumes that that the source can never be longer than the destination. There are now a legion of attackers who will exploit this code and harm its users. Modern C programs often have to work in the presence of attackers.
- camgunz 7y agoYeah I think strlcpy is way better exactly for this reason. I'm sure the idea behind returning the pointer was call chaining, but you shouldn't ever be doing that anyway, and with strlcpy you basically can't do an off-by-one.
- dwheeler 7y agoIt's true that strlcpy is easier to use. One challenge is that strlcpy always reads its inputs to completion, even when it is not needed to make the copy, because it has to compute the total length of the screen ignoring limits. In some circumstances that is a problem.
- caf 7y agosize_t is unsigned, so (dsize <= 0) is identical to (dsize == 0) ;)
- dwheeler 7y agoThat is true, but I find the less than or equal to be logically clearer. YMMV.