On 12/14/22 23:51, Alejandro Colomar wrote: > > > On 12/14/22 23:45, Alejandro Colomar wrote: >> Hi, >> >> I was rewriting the strncat(3) manual page, and when I tried to compile the >> example program, I got a surprise from the compiler. >> >> Here goes the page: >> >> >>    strncat(3)               Library Functions Manual              strncat(3) >> >>    NAME >>           strncat  -  concatenate  a  null‐padded  character sequence into a >>           string >> >>    LIBRARY >>           Standard C library (libc, -lc) >> >>    SYNOPSIS >>           #include >> >>           char *strncat(char *restrict dst, const char src[restrict .sz], >>                          size_t sz); >> >>    DESCRIPTION >>           This function catenates the input character sequence contained  in >>           a  null‐padded  fixed‐width  buffer,  into  a string at the buffer >>           pointed to by dst.  The programmer is responsible for allocating a >>           buffer large enough, that is, strlen(dst) + strnlen(src, sz) + 1. >> >>           An implementation of this function might be: >> >>               char * >>               strncat(char *restrict dst, const char *restrict src, size_t sz) >>               { >>                   int   len; >>                   char  *end; >> >>                   len = strnlen(src, sz); >>                   end = dst + strlen(dst); >>                   end = mempcpy(end, src, len); >>                   *end = '\0'; >> >>                   return dst; >>               } >> >>    RETURN VALUE >>           strncat() returns dest. >> >>    ATTRIBUTES >>           [...] >> >>    STANDARDS >>           POSIX.1‐2001, POSIX.1‐2008, C89, C99, SVr4, 4.3BSD. >> >>    CAVEATS >>           The  name of this function is confusing.  This function has no re‐ >>           lation with strncpy(3). >> >>           If the destination buffer is not large enough, the behavior is un‐ >>           defined.  See _FORTIFY_SOURCE in feature_test_macros(7). >> >>    BUGS >>           This function  can  be  very  inefficient.   Read  about  Shlemiel >>           the       painter      ⟨https://www.joelonsoftware.com/2001/12/11/ >>           back-to-basics/⟩. >> >>    EXAMPLES >>           #include >>           #include >>           #include >> >>           int >>           main(void) >>           { >>               char    buf[BUFSIZ]; >>               size_t  len; >> >>               buf[0] = '\0';  // There’s no ’cpy’ function to this ’cat’. >>               strncat(buf, "Hello ", 6); >>               strncat(buf, "world", 42);  // Padding null bytes ignored. >>               strncat(buf, "!", 1); >>               len = strlen(buf); >>               printf("[len = %zu]: <%s>\n", len, buf); >> >>               exit(EXIT_SUCCESS); >>           } >> >>    SEE ALSO >>           string(3), string_copy(3) >> >>    Linux man‐pages (unreleased)      (date)                       strncat(3) >> >> >> And when you compile that, you get: >> >> $ cc -Wall -Wextra ./strncat.c >> ./strncat.c: In function ‘main’: >> ./strncat.c:12:12: warning: ‘strncat’ specified bound 6 equals source length >> [-Wstringop-overflow=] >>     12 |            strncat(buf, "Hello ", 6); >>        |            ^~~~~~~~~~~~~~~~~~~~~~~~~ >> ./strncat.c:14:12: warning: ‘strncat’ specified bound 1 equals source length >> [-Wstringop-overflow=] >>     14 |            strncat(buf, "!", 1); >>        |            ^~~~~~~~~~~~~~~~~~~~ >> >> >> So, what?  Where's the problem?  This function does exactly that: "take an >> unterminated character sequence and catenate it to an existing string".  Clang >> seems to be fine with the code. > > Maybe it's saying that I should be using strncat(buf, "!"); because the length oops; of course, I meant strcat(). > is useless? > >> >> Cheers, >> >> Alex >> >> > --