memset, memset_explicit, memset_s
Определено в заголовочном файле <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 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
См. также
|
(C11) | копирует один буфер в другой (функция) |
|
(C95) | копирует заданный широкий символ в каждую позицию в массиве широких символов (функция) |
Документация C++ для memset |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/string/byte/memset