命名空间
变体
操作

memset, memset_explicit, memset_s

来自 cppreference.cn
< 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 复制到 dest 所指向的对象的前 count 个字符中的每一个。
如果访问发生在 dest 数组末尾之外,则行为未定义。如果 dest 是空指针,则行为未定义。
2)(1) 相同,但对敏感信息是安全的。
3)(1) 相同,但以下错误在运行时被检测到,并在将 ch 存储到目标范围 [dest, dest+destsz) 的每个位置后,调用当前安装的 约束处理函数,如果 destdestsz 本身有效
  • dest 是空指针
  • destszcount 大于 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 bug 8537),则 memset 可能会被优化掉(在 as-if 规则下)。因此,此函数不能用于擦除内存(例如,用零填充存储密码的数组)。

memset_explicitmemset_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 函数

[编辑] 参见

将一个缓冲区复制到另一个缓冲区
(函数) [编辑]
将给定的宽字符复制到宽字符数组的每个位置
(函数) [编辑]
C++ 文档 关于 memset