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 может быть удалена оптимизатором (в соответствии с правилами «как если бы»), если к объекту, изменённому этой функцией, больше не обращаются до конца его времени жизни (например, ошибка GCC 8537). По этой причине эту функцию нельзя использовать для очистки памяти (например, для заполнения нулями массива, в котором хранился пароль).
Эта оптимизация запрещена для memset_explicit и memset_s: гарантируется, что они выполняют запись в память.
Сторонние решения для этой задачи включают FreeBSD explicit_bzero и Microsoft SecureZeroMemory.
Пример
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>
#include <string.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
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
- 7.26.6.1 Функция memset (стр. 383)
- 7.26.6.2 Функция memset_explicit (стр. 383)
- K.3.7.5.1 Функция memset_s (стр. 651)
- Стандарт 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/c/string/byte/memset