C/C++---memset()初始化
memset
是 C/C++ 标准库中用于内存块初始化的函数,定义在 <cstring>
头文件中。它的核心功能是将一块连续内存的每个字节都设置为指定的值,常用于初始化数组、结构体等数据结构。
一、函数原型
void* memset(void* ptr, int value, size_t num);
- 参数说明:
ptr
:指向要初始化的内存块的起始地址(必须是可修改的内存,如数组、动态分配的内存等)。value
:要设置的值(虽然类型是int
,但实际只会使用其低 8 位,即unsigned char
范围内的值)。num
:要设置的字节数(size_t
类型,通常是内存块的总大小)。
- 返回值:返回指向内存块起始地址的指针(即
ptr
)。
二、工作原理
memset
会从 ptr
指向的地址开始,逐个字节地将内存设置为 value
的低 8 位。例如:
int arr[5];
memset(arr, 0, sizeof(arr)); // 将arr的每个字节都设为0
sizeof(arr)
计算数组总字节数(5 * 4 = 20
字节,假设int
为 4 字节)。memset
会将这 20 个字节全部设置为0x00
,最终数组每个元素都为0
。
三、使用场景
-
初始化数组为 0 或 -1
最常见的用法是将数组初始化为全 0 或全 -1(因二进制特性,见下文注意事项):int a[100]; memset(a, 0, 100 * sizeof(int)); // 全0初始化char str[20]; memset(str, '\0', 20); // 字符串结束符初始化(等价于0)
-
清空结构体/缓冲区
用于重置结构体或内存缓冲区的内容:struct Student {int id;char name[20]; }; Student s; memset(&s, 0, sizeof(Student)); // 结构体成员全设为0
-
快速填充字符数组
对字符数组(每个元素占 1 字节)可直接填充指定字符:char buf[10]; memset(buf, 'a', 10); // 数组元素全为 'a'(ASCII码97)
四、关键注意事项
-
按字节赋值的局限性
memset
是逐字节设置的,因此仅适用于以下情况:- 目标类型为单字节类型(如
char
、unsigned char
)。 - 希望将多字节类型(如
int
、long
)的每个字节都设为相同值(如 0 或 -1)。
❌ 错误示例(对
int
数组填充非 0/-1 的值):int arr[3]; memset(arr, 1, 3 * sizeof(int)); // 错误!结果不是 [1,1,1]
原因:
int
占 4 字节,memset
会将每个字节设为0x01
,实际每个元素为0x01010101
(十进制 16843009),而非 1。 - 目标类型为单字节类型(如
-
value
参数的有效范围
虽然value
类型是int
,但实际只使用低 8 位(0~255
或-128~127
)。例如:memset(ptr, 256, num); // 等价于 memset(ptr, 0, num)(256的低8位为0) memset(ptr, -1, num); // 等价于填充 0xFF(因-1的二进制补码为全1)
-
避免越界访问
num
参数必须小于等于ptr
指向的内存块大小,否则会导致缓冲区溢出,引发未定义行为(如程序崩溃、数据损坏)。 -
与
std::fill
的区别
C++ 中的std::fill
是更通用的初始化工具,按元素赋值而非按字节,适用于任何类型:#include <algorithm> // 需包含此头文件 int arr[3]; std::fill(arr, arr + 3, 1); // 正确将每个元素设为1(按int类型赋值)
memset
速度更快(底层优化),但适用场景有限。std::fill
更灵活,支持任意值初始化,但性能略低。
五、常见错误用法
- 对非字节类型填充任意值(如上述
int
数组填充 1)。 - 错误计算
num
大小(如用元素个数代替字节数):int arr[10]; memset(arr, 0, 10); // 错误!仅初始化前10字节(不足3个int元素)
- 对只读内存(如字符串常量)使用
memset
:char* str = "hello"; memset(str, 'a', 5); // 错误!字符串常量不可修改,会导致崩溃
memset
是高效的内存初始化工具,核心作用是按字节批量设置内存值,但需注意:
- 仅适用于单字节类型或多字节类型的全 0/-1 初始化。
- 严格控制
num
参数,避免越界。 - 复杂类型的初始化优先考虑
std::fill
等更安全的方法。