memset, memset_explicit, memset_s
From cppreference.net
|
定义于头文件
<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
为空指针,则行为未定义。
2)
与
(1)
相同,但对敏感信息安全。
3)
与
(1)
相同,区别在于以下错误会在运行时被检测到,并在目标范围
[
dest, dest
+
destsz
)
的每个位置存储
ch
后(若
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
。
注释
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 函数 (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函数(页:333)
- C89/C90 标准 (ISO/IEC 9899:1990):
-
- 4.11.6.1 memset 函数
参见
|
(C11)
|
复制一个缓冲区到另一个缓冲区
(函数) |
|
(C95)
|
将给定的宽字符复制到宽字符数组的每个位置
(函数) |
|
C++ 文档
关于
memset
|
|