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[0] (если dest — нулевой указатель или destsz — ноль или больше RSIZE_MAX) и может перезаписать остальную часть целевого массива неопределёнными значениями.Примечания
Как исправлено в DR 468 после C11, 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"; // 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
Ссылки
- Стандарт 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 |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/string/byte/strncpy