strncpy, strncpy_s
|
Определено в заголовочном файле
<string.h>
|
||
| (1) | ||
|
char
*
strncpy
(
char
*
dest,
const
char
*
src,
size_t
count
)
;
|
(до C99) | |
|
char
*
strncpy
(
char
*
restrict
dest,
const
char
*
restrict
src,
size_t
count
)
;
|
(начиная с C99) | |
|
errno_t strncpy_s
(
char
*
restrict
dest, rsize_t destsz,
const char * restrict src, rsize_t count ) ; |
(2) | (начиная с C11) |
count
символов из массива символов, на который указывает
src
(включая завершающий нулевой символ, но не включая символы после нулевого символа), в массив символов, на который указывает
dest
.
count
достигается до того, как весь массив
src
был скопирован, результирующий массив символов не завершается нулевым символом.
src
значение
count
не достигнуто, в
dest
записываются дополнительные нулевые символы до тех пор, пока не будет записано в общей сложности
count
символов.
dest
или
src
не являются указателями на символьный массив (включая случай, когда
dest
или
src
являются нулевыми указателями), если размер массива, на который указывает
dest
, меньше
count
, или если размер массива, на который указывает
src
, меньше
count
и он не содержит нулевого символа.
count
, она останавливается после записи завершающего нулевого символа (если в источнике не было нуля, она записывает его в
dest
[
count
]
и затем останавливается). Кроме того, следующие ошибки обнаруживаются во время выполнения и вызывают текущую установленную
функцию обработки ограничений
:
-
-
srcилиdestявляется нулевым указателем -
destszравен нулю или больше RSIZE_MAX -
countбольше RSIZE_MAX -
countбольше или равенdestsz, ноdestszменьше или равен strnlen_s ( src, count ) , другими словами, произошло бы усечение - возникло бы перекрытие между исходной и целевой строками
-
dest
<
strnlen_s
(
src, destsz
)
<=
destsz
; другими словами, ошибочное значение
destsz
не выявляет надвигающееся переполнение буфера. Поведение не определено, если размер массива символов, на который указывает
src
<
strnlen_s
(
src, count
)
<
destsz
; другими словами, ошибочное значение
count
может допустить переполнение буфера.
-
Как и все функции с проверкой границ,
strncpy_sгарантированно доступна только если __STDC_LIB_EXT1__ определено реализацией и если пользователь определяет __STDC_WANT_LIB_EXT1__ как целочисленную константу 1 перед включением <string.h> .
Содержание |
Параметры
| dest | - | указатель на массив символов для копирования в |
| src | - | указатель на массив символов для копирования из |
| count | - | максимальное количество символов для копирования |
| destsz | - | размер буфера назначения |
Возвращаемое значение
dest
dest
не является нулевым указателем и
destsz
не равен нулю и не превышает
RSIZE_MAX
) и может заполнить остальной массив назначения неопределенными значениями.
Примечания
Как исправлено пост-C11 DR 468,
strncpy_s
, в отличие от
strcpy_s
, разрешено перезаписывать оставшуюся часть целевого массива только при возникновении ошибки.
В отличие от
strncpy
,
strncpy_s
не заполняет конечный массив нулями. Это распространённый источник ошибок при конвертации существующего кода в версию с проверкой границ.
Хотя усечение для соответствия целевому буферу представляет собой угрозу безопасности и, следовательно, нарушение ограничений времени выполнения для
strncpy_s
, можно получить поведение с усечением, указав
count
равным размеру целевого массива минус один: функция скопирует первые
count
байт и добавит нулевой терминатор как обычно:
strncpy_s
(
dst,
sizeof
dst, src,
(
sizeof
dst
)
-
1
)
;
Пример
#define __STDC_WANT_LIB_EXT1__ 1 #include <string.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> int main(void) { char src[] = "hi"; char dest[6] = "abcdef"; // нет нулевого терминатора strncpy(dest, src, 5); // записывает пять символов 'h', 'i', '\0', '\0', '\0' в dest printf("strncpy(dest, src, 5) для dest размером 6 байт дает: "); for (size_t n = 0; n < sizeof dest; ++n) { char c = dest[n]; c ? printf("'%c' ", c) : printf("'\\0' "); } printf("\nstrncpy(dest2, src, 2) для dst размером 2 байта дает: "); char dest2[2]; strncpy(dest2, src, 2); // усечение: записывает два символа 'h', 'i' в dest2 for (size_t n = 0; n < sizeof dest2; ++n) { char c = dest2[n]; c ? printf("'%c' ", c) : printf("'\\0' "); } printf("\n"); #ifdef __STDC_LIB_EXT1__ set_constraint_handler_s(ignore_handler_s); char dst1[6], src1[100] = "hello"; errno_t r1 = strncpy_s(dst1, 6, src1, 100); // записывает 0 в r1, 6 символов в dst1 printf("dst1 = \"%s\", r1 = %d\n", dst1,r1); // 'h','e','l','l','o','\0' в dst1 char dst2[5], src2[7] = {'g','o','o','d','b','y','e'}; errno_t r2 = strncpy_s(dst2, 5, src2, 7); // копирование переполняет массив назначения printf("dst2 = \"%s\", r2 = %d\n", dst2,r2); // записывает ненулевое значение в r2, '\0' в dst2[0] char dst3[5]; errno_t r3 = strncpy_s(dst3, 5, src2, 4); // записывает 0 в r3, 5 символов в dst3 printf("dst3 = \"%s\", r3 = %d\n", dst3,r3); // 'g', 'o', 'o', 'd', '\0' в dst3 #endif }
Возможный вывод:
strncpy(dest, src, 5) для dst размером 6 байт дает: 'h' 'i' '\0' '\0' '\0' 'f' strncpy(dest2, src, 2) для dst размером 2 байта дает: 'h' 'i' dst1 = "hello", r1 = 0 dst2 = "", r2 = 22 dst3 = "good", r3 = 0
Ссылки
- Стандарт C17 (ISO/IEC 9899:2018):
-
- 7.24.2.4 Функция strncpy (стр. 265)
-
- K.3.7.1.4 Функция strncpy_s (стр. 447-448)
- Стандарт C11 (ISO/IEC 9899:2011):
-
- 7.24.2.4 Функция strncpy (стр: 363-364)
-
- K.3.7.1.4 Функция strncpy_s (стр: 616-617)
- Стандарт C99 (ISO/IEC 9899:1999):
-
- 7.21.2.4 Функция strncpy (стр: 326-327)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
-
- 4.11.2.4 Функция strncpy
Смотрите также
|
(C11)
|
копирует одну строку в другую
(функция) |
|
(C11)
|
копирует один буфер в другой
(функция) |
|
(dynamic memory TR)
|
выделяет копию строки до указанного размера
(функция) |
|
C++ documentation
для
strncpy
|
|