Копировать или соединить строки с заданием конечного размера
#include <string.h>size_t strlcpy( char *dst,const char *src,size_t size );size_t strlcat( char *dst,const char *src,size_t size );
libc
Функции strlcpy() и strlcat() копируют и объединяют строки соответственно. Они разработаны, чтобы быть более безопасными, последовательными и менее подверженными ошибкам заменами для strncpy() и strncat().
В отличие от данных функций, strlcpy() и strlcat() берут полный размер буфера (а не только длину) и гарантируют NUL
-терминированный результат (пока size больше 0
или, в случае strlcat(), если в dst есть хотя бы один свободный байт).
![]() | Следует оставить байт для NUL в size. Также следует обратить внимание, что strlcpy() и strlcat() работают только с C-строками. Это означает, что для strlcpy() src должна завершаться NUL , а для strlcat() и src, и dst должны завершаться NUL . |
Функция strlcpy() копирует до size – 1
символов из строки src, заканчивающейся NUL
, в dst, завершая результат символом NUL
.
Функция strlcat() добавляет NUL
-терминированную строку src в конец dst. Она добавит не более size — strlen( dst ) — 1 байт, завершая результат символом NUL
.
Итоговая длина строки:
![]() | Если strlcat() проходит через size символов и не находит NUL , считается, что длина строки равна size, а целевая строка не завершается NUL (поскольку не было места для NUL ). Это предотвращает strlcat() от выхода за конец строки. На практике этого не должно происходить (поскольку это означает, что либо size некорректен, либо что dst не является строкой «C»). Проверка существует для предотвращения потенциальных проблем безопасности в коде. |
Следующий фрагмент кода иллюстрирует простейший случай:
char *s, *p, buf[BUFSIZ];...(void)strlcpy( buf, s, sizeof( buf ) );(void)strlcat( buf, p, sizeof( buf ) );
Чтобы обнаружить усечение строки, можно при создании пути использовать что-то наподобие этого:
char *dir, *file, pname[MAXPATHLEN];...if ( strlcpy( pname, dir, sizeof( pname ) ) >= sizeof( pname ) )goto toolong;if ( strlcat( pname, file, sizeof( pname ) ) >= sizeof( pname ) )goto toolong;
Поскольку известно, сколько символов было скопировано в первый раз, можно немного ускорить процесс, используя копирование вместо добавления:
char *dir, *file, pname[MAXPATHLEN];size_t n;...n = strlcpy( pname, dir, sizeof( pname ) );if ( n >= sizeof( pname ) )goto toolong;if ( strlcpy( pname + n, file, sizeof( pname ) - n ) >= sizeof( pname ) - n )goto toolong;
Однако можно усомниться в правильности таких оптимизаций, поскольку они сводят на нет всю задачу strlcpy() и strlcat().
Unix
OpenBSD
snprintf(), strncpy(), strncat()
Предыдущий раздел: Описание API системной библиотеки