strncpy, strncpy_s
Определено в заголовочном файле <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) |
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__, а пользователь перед включением <string.h> определяет __STDC_WANT_LIB_EXT1__ как целочисленную константу 1.Параметры
| 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 <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) | копирует один буфер в другой (функция) |
|
(технический отчет о динамической памяти) | выделяет память для копии строки указанного размера (функция) |
Документация по C++ для strncpy |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/c/string/byte/strncpy