strncpy, strncpy_s
Из ru.cppreference.net
| Определено в заголовке <string.h>
|
||
char* strncpy( char* dest, const char* src, size_t count );
|
(1) | (до 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) |
1) Копирует не более
count символов массива символов, на который указывает src (включая завершающий нулевой символ, но не любые символы, следующие за нулевым символом), в массив символов, на который указывает dest. Если
count достигнут до того, как весь массив src был скопирован, результирующий массив символов не завершается нулём. Если после копирования завершающего нулевого символа из
src count не достигнут, дополнительные нулевые символы записываются в dest до тех пор, пока не будет записано в общей сложности count символов. Поведение не определено, если массивы символов перекрываются, если
dest или src не является указателем на массив символов (в том числе если dest или src является нулевым указателем), если размер массива, на который указывает dest, меньше count, или если размер массива, на который указывает src, меньше count и он не содержит нулевого символа.2) То же, что и (1), за исключением того, что функция не продолжает запись нулей в массив назначения для заполнения до
count, она останавливается после записи завершающего нулевого символа (если в источнике не было нуля, она записывает его в dest[count], а затем останавливается). Также следующие ошибки обнаруживаются во время выполнения и вызывают функцию обработчика ограничений, установленную в данный момент:
srcилиdestявляется нулевым указателемdestszравно нулю или больше RSIZE_MAXcountбольше RSIZE_MAXcountбольше или равно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 | - | размер целевого буфера |
Возвращаемое значение
1) возвращает копию
dest2) возвращает ноль при успехе, возвращает ненулевое значение при ошибке. Также при ошибке записывает ноль в
dest[0] (если dest не является нулевым указателем или destsz не равно нулю или не больше RSIZE_MAX) и может испортить остаток целевого массива неопределенными значениями.Примечания
Как исправлено DR 468 после C11, strncpy_s, в отличие от strcpy, имеет право испортить остаток целевого массива только в случае ошибки.
В отличие от strncpy, strncpy_s не заполняет целевой массив нулями. Это частая причина ошибок при преобразовании существующего кода в версию с проверкой границ.
Хотя усечение для соответствия целевому буферу является риском безопасности и, следовательно, нарушением ограничений времени выполнения для strncpy_s, возможно получить поведение усечения, указав count равным размеру целевого массива минус один: он скопирует первые count байт и добавит нулевой терминатор, как обычно: strncpy_s(dst, sizeof dst, src, (sizeof dst)-1);
Пример
Запустить этот код
#define __STDC_WANT_LIB_EXT1__ 1
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char src[] = "hi";
char dest[6] = "abcdef"; // no null terminator
strncpy(dest, src, 5); // writes five characters 'h', 'i', '\0', '\0', '\0' to dest
printf("strncpy(dest, src, 5) to a 6-byte dest gives : ");
for (size_t n = 0; n < sizeof dest; ++n) {
char c = dest[n];
c ? printf("'%c' ", c) : printf("'\\0' ");
}
printf("\nstrncpy(dest2, src, 2) to a 2-byte dst gives : ");
char dest2[2];
strncpy(dest2, src, 2); // truncation: writes two characters 'h', 'i', to 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); // writes 0 to r1, 6 characters to dst1
printf("dst1 = \"%s\", r1 = %d\n", dst1,r1); // 'h','e','l','l','o','\0' to dst1
char dst2[5], src2[7] = {'g','o','o','d','b','y','e'};
errno_t r2 = strncpy_s(dst2, 5, src2, 7); // copy overflows the destination array
printf("dst2 = \"%s\", r2 = %d\n", dst2,r2); // writes nonzero to r2,'\0' to dst2[0]
char dst3[5];
errno_t r3 = strncpy_s(dst3, 5, src2, 4); // writes 0 to r3, 5 characters to dst3
printf("dst3 = \"%s\", r3 = %d\n", dst3,r3); // 'g', 'o', 'o', 'd', '\0' to dst3
#endif
}
Возможный вывод:
strncpy(dest, src, 5) to a 6-byte dst gives : 'h' 'i' '\0' '\0' '\0' 'f'
strncpy(dest2, src, 2) to a 2-byte dst gives : 'h' 'i'
dst1 = "hello", r1 = 0
dst2 = "", r2 = 22
dst3 = "good", r3 = 0
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
- 7.24.2.4 Функция strncpy (стр.: TBD)
- K.3.7.1.4 Функция strncpy_s (стр.: TBD)
- Стандарт 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++ для strncpy
| |