命名空间
变体
操作

memset、memset_explicit、memset_s

来自 cppreference.com
< 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 错误 8537),则 memset 可能会被优化掉(根据 如同 规则)。因此,此函数不能用于清除内存(例如,用零填充存储密码的数组)。

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++ 文档 for memset