Spec-Zone.ru › C

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)
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_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 - размер целевого буфера

Возвращаемое значение

1) возвращает копию dest
2) возвращает ноль при успехе, возвращает ненулевое значение при ошибке. Также при ошибке записывает ноль в 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

См. также

strcpystrcpy_s
(C11)
копирует одну строку в другую
(функция)
memcpymemcpy_s
(C11)
копирует один буфер в другой
(функция)
strndup
(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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API