什么是 memset?
memset 是 C 标准库 <string.h> (或 <memory.h>) 中的一个函数,它的作用是将一块内存区域中的每个字节都设置为指定的值。

(图片来源网络,侵删)
你可以把它想象成用一个“油漆桶”去涂刷一块内存区域,把整个区域都染成同一种颜色(同一个字节值)。
函数原型
#include <string.h> // 或 <memory.h> void *memset(void *ptr, int value, size_t num);
参数详解
-
void *ptr:- 这是一个指向要被操作的内存区域的起始地址的指针。
- 它的类型是
void *,意味着它可以接受任何类型的指针(如int *,char *,struct *等)。 - 这个内存区域必须是你拥有并且可以修改的,不能是只读的内存。
-
int value:- 这是你要设置的值。
- 特别注意:虽然参数类型是
int,但memset是按字节操作的,它会把这个int值的低 8 位(一个字节)复制到目标内存区域的每一个字节中。 - 你只会使用
0或0xFF(即-1)这样的值,因为其他值可能会导致非预期的结果(用1去初始化一个int,得到的结果不是1,而是0x01010101)。
-
size_t num:
(图片来源网络,侵删)- 这是你要设置的字节数。
size_t是一个无符号整数类型,足以表示系统中可能的最大内存块大小。
返回值
- 函数返回一个
void *类型的指针,这个指针就是传入的第一个参数ptr的值。 - 这个返回值主要是为了方便进行函数链式调用,但在实际使用中,我们通常会忽略它,直接使用我们传入的指针。
使用示例
示例 1:最常见的用法 - 数组清零
这是 memset 最经典和最安全的用途,将一块内存全部设置为 0。
#include <stdio.h>
#include <string.h>
int main() {
int arr[10];
int i;
// 打印初始化前的随机值
printf("Before memset:\n");
for (i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("\n\n");
// 将 arr 数组的前 10 * sizeof(int) 个字节全部设置为 0
// 因为 arr 是一个包含 10 个 int 的数组,所以总字节数是 10 * 4 = 40
memset(arr, 0, sizeof(arr));
// 打印清零后的值
printf("After memset (with 0):\n");
for (i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
输出:
Before memset:
4202528 0 4202528 0 4202528 0 4202528 0 4202528 0
After memset (with 0):
0 0 0 0 0 0 0 0 0 0
示例 2:将内存设置为 -1
将内存的每个字节都设置为 0xFF(即 11111111),对于有符号整数类型(如 int, char),这通常表示 -1。
#include <stdio.h>
#include <string.h>
int main() {
int arr[5];
int i;
// 将数组所有字节设置为 0xFF
memset(arr, 0xFF, sizeof(arr));
printf("Array after memset with 0xFF (-1):\n");
for (i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
输出:

(图片来源网络,侵删)
Array after memset with 0xFF (-1):
-1 -1 -1 -1 -1
示例 3:一个常见的错误用法
初学者常常会犯一个错误:试图用 memset 来将一个数组设置为非 0 或非 -1 的特定值。
#include <stdio.h>
#include <string.h>
int main() {
int arr[5];
int i;
// 错误!不要这样做!
// 这会把 arr 的每个字节都设置为 1
// 对于 4 字节的 int,每个元素会变成 0x01010101,即 16843009
memset(arr, 1, sizeof(arr));
printf("Array after incorrect memset with 1:\n");
for (i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
输出:
Array after incorrect memset with 1:
16843009 16843009 16843009 16843009 16843009
这显然不是我们想要的 1, 2, 3, 4, 5,如果要将数组初始化为特定值,应该使用循环。
memset vs. memcpy vs. memmove
这是一个非常容易混淆的点,这里做一个简单的对比:
| 函数 | 功能 | 参数 |
|---|---|---|
memset |
设置内存区域为同一个值。 | ptr, value, num |
memcpy |
复制一块内存到另一块内存。 | dest, src, num |
memmove |
移动一块内存到另一块内存,源和目标区域可以重叠。 | dest, src, num |
关键区别:
memset用于初始化或清空。memcpy用于复制,当源和目标内存不重叠时使用,效率更高。memmove用于移动,当源和目标内存可能重叠时使用,更安全。
- 功能:
memset是一个快速、底层的内存设置工具。 - 用途:最常用于将内存块清零 (
memset(ptr, 0, size))。 - 核心:它是按字节操作的,不是按元素。
- 警告:不要用它来设置非 0 或非 -1 的特定值给多字节数据类型(如
int,float,struct)。 - 头文件:使用时必须包含
<string.h>。
memset 是 C 语言程序员工具箱中一个基础且强大的工具,理解它的正确用法和局限性非常重要。
