On 12/16/22 20:03, Alejandro Colomar wrote:
On 12/16/22 19:47, Stefan Puiu wrote:On Thu, Dec 15, 2022 at 2:46 AM Alejandro Colomar <alx.manpages@xxxxxxxxx> wrote:An implementation of these functions might be: char * stpcpy(char *restrict dst, const char *restrict src) { char *end; end = mempcpy(dst, src, strlen(src)); *end = '\0'; return end; } char * strcpy(char *restrict dst, const char *restrict src) { stpcpy(dst, src); return dst; } char * strcat(char *restrict dst, const char *restrict src) { stpcpy(dst + strlen(dst), src); return dst; }Are you sure this section adds any value? I think good documentation should explain how a function works without delving into the interpretation.To be honest, this page doesn't benefit too much from it. strcpy(3)/strcat(3) are dead simple, and the explanations above should be enough.However, the same thing in strncpy(3) and strncat(3) is very helpful, IMO. For consistency I just showed trivial implementations in all of the pages. (And in fact, there was an example implementation in the old strncat(3) and maybe a few others, IIRC.)Also, people might get confused and think this is the actual implementation.I don't think there's any problem if one believes this is the implementation. Except for stpcpy(3), in which I preferred readability, they are actually quite good implementations. A faster implementation of stpcpy(3) might be done in terms of memccpy(3).Funnily enough, I just checked what musl libc does, and it's the same as shown here:alx@debian:~/src/musl/musl$ grepc -tfd strcpy ./src/string/strcpy.c:3: char *strcpy(char *restrict dest, const char *restrict src) { __stpcpy(dest, src); return dest; } alx@debian:~/src/musl/musl$ grepc -tfd strcat ./src/string/strcat.c:3: char *strcat(char *restrict dest, const char *restrict src) { strcpy(dest + strlen(dest), src); return dest; }
And considering memccpy(3) is defined in terms of memchr(3) and mempcpy(3) in glibc, I don't feel so bad about my own stpcpy(3) :). See:
alx@debian:~/src/gnu/glibc$ grepc -tfd __memccpy ./string/memccpy.c:30: void * __memccpy (void *dest, const void *src, int c, size_t n) { void *p = memchr (src, c, n); if (p != NULL) return __mempcpy (dest, src, p - src + 1); memcpy (dest, src, n); return NULL; } Cheers, Alex
RETURN VALUE stpcpy() This function returns a pointer to the terminating null byte at the end of the copied string. strcpy() strcat() These functions return dest. ATTRIBUTES For an explanation of the terms used in this section, see attrib‐ utes(7).┌────────────────────────────────────────────┬───────────────┬─────────┐ │Interface │ Attribute │ Value │ ├────────────────────────────────────────────┼───────────────┼─────────┤ │stpcpy(), strcpy(), strcat() │ Thread safety │ MT‐Safe │ └────────────────────────────────────────────┴───────────────┴─────────┘STANDARDS stpcpy() POSIX.1‐2008. strcpy() strcat() POSIX.1‐2001, POSIX.1‐2008, C89, C99, SVr4, 4.3BSD. CAVEATS The strings src and dst may not overlap. If the destination buffer is not large enough, the behavior is unde‐ fined. See _FORTIFY_SOURCE in feature_test_macros(7). BUGS strcat() This function can be very inefficient. Read about Shlemiel the painter ⟨https://www.joelonsoftware.com/2001/12/11/ back-to-basics/⟩.I'm not sure this is a bug, rather a design limitation. Maybe it belongs in NOTES or CAVEATS?Yeah, I had been thinking of downgrading it. I'll do it.Also, I think this can be summarized along the lines of 'strcat needs to walk the destination buffer to find the null terminator, so it has linear complexity with respect to the size of the destination buffer up to the terminator' (hmm, I'm sure this can be expressed more concisely), so the page is more self contained. Outside links sometimes go dead, like on Wikipedia, so I think just in case, it helps to make explicit the point that you want the reader to study further in the URL.I wasn't inspired to write it short enough to not be too verbose. Maybe I'll write something based on your suggestion.Regards, Stefan.Thanks for the review! Cheers, AlexEXAMPLES #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char *p; char buf1[BUFSIZ]; char buf2[BUFSIZ]; size_t len; p = buf1; p = stpcpy(p, "Hello "); p = stpcpy(p, "world"); p = stpcpy(p, "!"); len = p - buf1; printf("[len = %zu]: ", len); puts(buf1); // "Hello world!" strcpy(buf2, "Hello "); strcat(buf2, "world"); strcat(buf2, "!"); len = strlen(buf2); printf("[len = %zu]: ", len); puts(buf2); // "Hello world!" exit(EXIT_SUCCESS); } SEE ALSO strdup(3), string(3), wcscpy(3), string_copy(7) Linux man‐pages (unreleased) (date) strcpy(3) -- <http://www.alejandro-colomar.es/>
-- <http://www.alejandro-colomar.es/>
Attachment:
OpenPGP_signature
Description: OpenPGP digital signature