Spec-Zone.ru › C

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)
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__, а пользователь перед включением <string.h> определяет __STDC_WANT_LIB_EXT1__ как целочисленную константу 1.

Параметры

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 <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

См. также

strcpystrcpy_s
(C11)
копирует одну строку в другую
(функция)
memcpymemcpy_s
(C11)
копирует один буфер в другой
(функция)
strndup
(технический отчет о динамической памяти)
выделяет память для копии строки указанного размера
(функция)
Документация по C++ для strncpy

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/c/string/byte/strncpy

Spec-Zone.ru

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