Namespaces
Variants

memset, memset_explicit, memset_s

From cppreference.net
< c ‎ | string ‎ | byte
Определено в заголовке <string.h>
void * memset ( void * dest, int ch, size_t count ) ;
(1)
void * memset_explicit ( void * dest, int ch, size_t count ) ;
(2) (начиная с C23)
errno_t memset_s ( void * dest, rsize_t destsz, int ch, rsize_t count ) ;
(3) (начиная с C11)
1) Копирует значение ( unsigned char ) ch в каждый из первых count символов объекта, на который указывает dest .
Поведение не определено, если доступ происходит за пределами массива dest. Поведение не определено, если dest является нулевым указателем.
2) То же, что и (1) , за исключением того, что безопасно для конфиденциальной информации.
3) То же, что и (1) , за исключением того, что следующие ошибки обнаруживаются во время выполнения и вызывают текущую установленную функцию обработки ограничений после сохранения ch в каждой позиции диапазона назначения [ dest, dest + destsz ) , если dest и destsz сами являются допустимыми:
  • dest является нулевым указателем
  • destsz или count больше RSIZE_MAX
  • count больше destsz (произойдет переполнение буфера)
Поведение не определено, если размер массива символов, на который указывает dest < count <= destsz ; другими словами, ошибочное значение destsz не выявляет надвигающееся переполнение буфера.
Как и все функции с проверкой границ, memset_s гарантированно доступна только если __STDC_LIB_EXT1__ определено реализацией и если пользователь определяет __STDC_WANT_LIB_EXT1__ как целочисленную константу 1 до включения <string.h> .

Содержание

Параметры

dest - указатель на заполняемый объект
ch - байт для заполнения
count - количество байт для заполнения
destsz - размер целевого массива

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

1,2) Копия dest
3) ноль при успехе, не ноль при ошибке. Также при ошибке, если dest не является нулевым указателем и destsz допустим, записывает destsz заполняющих байтов ch в целевой массив.

Примечания

memset может быть оптимизирован (в соответствии с правилами as-if ), если объект, изменяемый этой функцией, больше не используется до конца своего времени жизни (например, gcc bug 8537 ). По этой причине данная функция не может использоваться для очистки памяти (например, для заполнения нулями массива, в котором хранился пароль).

Эта оптимизация запрещена для memset_explicit и memset_s : они гарантированно выполняют запись в память.

Сторонние решения для этого включают FreeBSD explicit_bzero или Microsoft SecureZeroMemory .

Пример

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
    char str[] = "ghghghghghghghghghghgh";
    puts(str);
    memset(str,'a',5);
    puts(str);
#ifdef __STDC_LIB_EXT1__
    set_constraint_handler_s(ignore_handler_s);
    int r = memset_s(str, sizeof str, 'b', 5);
    printf("str = \"%s\", r = %d\n", str, r);
    r = memset_s(str, 5, 'c', 10);   // count is greater than destsz  
    printf("str = \"%s\", r = %d\n", str, r);
#endif
}

Возможный вывод:

ghghghghghghghghghghgh
aaaaahghghghghghghghgh
str = "bbbbbhghghghghghghghgh", r = 0
str = "ccccchghghghghghghghgh", r = 22

Ссылки

  • Стандарт C17 (ISO/IEC 9899:2018):
  • 7.24.6.1 Функция memset (стр: 270)
  • K.3.7.4.1 Функция memset_s (стр: 451)
  • Стандарт C11 (ISO/IEC 9899:2011):
  • 7.24.6.1 Функция memset (стр. 371)
  • K.3.7.4.1 Функция memset_s (стр. 621-622)
  • Стандарт C99 (ISO/IEC 9899:1999):
  • 7.21.6.1 Функция memset (стр: 333)
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
  • 4.11.6.1 Функция memset

Смотрите также

копирует один буфер в другой
(функция)
(C95)
копирует заданный широкий символ в каждую позицию массива широких символов
(функция)
C++ documentation для memset