Don't say "concatenate". Use "byte" instead of "character", and use standalone terminology rather than relying on the reader already having read string_copying(7). Don't say "width" when "size" was intended. Fix indenting of prototype. Simplify possible implementation, fixing a bug when the source string length and sz exceed INT_MAX. Say that strncat is rarely useful. Say that behavior is undefined if the destination is not a string. Simplify example by using plain sizeof rather than an nitems macro, by removing a confusingly-named 'maxsize' local, and by removing an unnecessary call to 'exit'. --- man3/strncat.3 | 54 +++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/man3/strncat.3 b/man3/strncat.3 index d0f777d36..9a7df474a 100644 --- a/man3/strncat.3 +++ b/man3/strncat.3 @@ -5,7 +5,8 @@ .\" .TH strncat 3 (date) "Linux man-pages (unreleased)" .SH NAME -strncat \- concatenate a null-padded character sequence into a string +strncat \- append non-null bytes from a source array to a string, +and null-terminate the result .SH LIBRARY Standard C library .RI ( libc ", " \-lc ) @@ -14,15 +15,18 @@ Standard C library .B #include <string.h> .P .BI "char *strncat(char *restrict " dst ", const char " src "[restrict ." sz ], -.BI " size_t " sz ); +.BI " size_t " sz ); .fi .SH 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 +This function appends at most +.I sz +non-null bytes from the array pointed to by +.I src +to the end of the string pointed to by .IR dst . -The programmer is responsible for allocating a destination buffer large enough, -that is, +.I dst +must point to a string contained in a buffer that is large enough, +that is, the buffer size must be at least .IR "strlen(dst) + strnlen(src, sz) + 1" . .P An implementation of this function might be: @@ -32,12 +36,7 @@ An implementation of this function might be: char * strncat(char *restrict dst, const char *restrict src, size_t sz) { - int len; - char *p; -\& - len = strnlen(src, sz); - p = dst + strlen(dst); - p = mempcpy(p, src, len); + char *p = mempcpy(dst + strlen(dst), src, strnlen(src, sz)); *p = \[aq]\e0\[aq]; \& return dst; @@ -67,11 +66,12 @@ C11, POSIX.1-2008. .SH HISTORY POSIX.1-2001, C89, SVr4, 4.3BSD. .SH CAVEATS -The name of this function is confusing. -This function has no relation to +The name of this function is confusing, as it has no relation to .BR strncpy (3). +This function is rarely useful in practice. .P -If the destination buffer is not large enough, +If the destination buffer does not already contain a string, +or is not large enough, the behavior is undefined. See .B _FORTIFY_SOURCE @@ -91,40 +91,32 @@ Shlemiel the painter #include <stdlib.h> #include <string.h> \& -#define nitems(arr) (sizeof((arr)) / sizeof((arr)[0])) -\& int main(void) { - size_t maxsize; -\& - // Null-padded fixed-width character sequences + // Null-padded fixed-size character sequences char pre[4] = "pre."; char new_post[50] = ".foo.bar"; \& // Strings char post[] = ".post"; char src[] = "some_long_body.post"; - char *dest; -\& - maxsize = nitems(pre) + strlen(src) \- strlen(post) + - nitems(new_post) + 1; - dest = malloc(sizeof(*dest) * maxsize); + char *dest = malloc(sizeof pre + strlen(src) \- strlen(post) + + sizeof new_post + 1); if (dest == NULL) err(EXIT_FAILURE, "malloc()"); \& - dest[0] = \[aq]\e0\[aq]; // There's no 'cpy' function to this 'cat'. - strncat(dest, pre, nitems(pre)); + dest[0] = \[aq]\e0\[aq]; // There's no `cpy' function to this `cat'. + strncat(dest, pre, sizeof pre); strncat(dest, src, strlen(src) \- strlen(post)); - strncat(dest, new_post, nitems(new_post)); + strncat(dest, new_post, sizeof new_post); \& puts(dest); // "pre.some_long_body.foo.bar" free(dest); - exit(EXIT_SUCCESS); } .EE .\" SRC END .in .SH SEE ALSO .BR string (3), -.BR string_copying (3) +.BR string_copying (7) -- 2.41.0