memset、memset_explicit、memset_s
来自 cppreference.com
在头文件 <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 复制到
dest
指向的对象的前 count
个字符中。 如果访问超出 dest 数组的末尾,则行为未定义。如果
dest
是空指针,则行为未定义。2) 与 (1) 相同,只是对敏感信息是安全的。
3) 与 (1) 相同,只是在运行时检测到以下错误,并在将
ch
存储到目标范围 [dest, dest+destsz) 的每个位置后,调用当前已安装的 约束处理程序 函数(如果 dest
和 destsz
本身有效)-
dest
是空指针 -
destsz
或count
大于 RSIZE_MAX -
count
大于destsz
(将发生缓冲区溢出)
-
如果
dest
指向的字符数组的大小 < count
<= destsz
,则行为未定义;换句话说,错误的 destsz
值不会暴露即将发生的缓冲区溢出。- 与所有边界检查函数一样,只有在实现定义了 __STDC_LIB_EXT1__ 并且用户在包含 <string.h> 之前将 __STDC_WANT_LIB_EXT1__ 定义为整数常量 1 时,
memset_s
才能保证可用。
内容 |
[编辑] 参数
dest | - | 指向要填充的对象的指针 |
ch | - | 填充字节 |
count | - | 要填充的字节数 |
destsz | - | 目标数组的大小 |
[编辑] 返回值
1,2)
dest
的副本3) 成功时为零,失败时为非零。此外,如果
dest
不是空指针并且 destsz
有效,则会将 destsz
个填充字节 ch
写入目标数组。[编辑] 备注
如果在该函数的整个生命周期中不再访问此函数修改的对象(例如,gcc 错误 8537),则 memset
可能会被优化掉(根据 如同 规则)。因此,此函数不能用于清除内存(例如,用零填充存储密码的数组)。
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 函数 (p: 270)
- K.3.7.4.1 memset_s 函数 (p: 451)
- C11 标准 (ISO/IEC 9899:2011)
- 7.24.6.1 memset 函数 (p: 371)
- K.3.7.4.1 memset_s 函数 (p: 621-622)
- C99 标准 (ISO/IEC 9899:1999)
- 7.21.6.1 memset 函数 (p: 333)
- C89/C90 标准 (ISO/IEC 9899:1990)
- 4.11.6.1 memset 函数
[编辑] 另请参见
(C11) |
将一个缓冲区复制到另一个缓冲区 (函数) |
(C95) |
将给定的宽字符复制到宽字符数组的每个位置 (函数) |
C++ 文档 for memset
|