chatgpt对memset的介绍下
memset
是 C 标准库中的一个内存操作函数,定义在 <string.h>
头文件中。它用于将一块用户空间的内存区域的所有字节设置为指定的值,常用于初始化或清零内存。当然,内核空间中也有同名的函数,不过引入的头文件是<linux/string.h>,而不是<string.h>,并且运行于内核空间中的memset是对内核空间的内存进行操作的。
函数原型
#include <string.h>
void *memset(void *s, int c, size_t n);
参数说明
s
:指向要填充的内存块的起始地址。c
:要设置的字节值(int
类型,但会转换为unsigned char
)。n
:要填充的字节数。
返回值
返回 s
指向的内存块的起始地址。
功能
- 用
c
填充s
指向的n
个字节。 - 通常用于初始化数组、结构体,或者清空内存区域。
示例
1. 初始化数组
#include <stdio.h>
#include <string.h>
int main() {
char buffer[10];
// 将 buffer 的所有字节设为 'A' (0x41)
memset(buffer, 'A', sizeof(buffer));
// 打印结果
for (int i = 0; i < 10; i++) {
printf("%c ", buffer[i]); // 输出:A A A A A A A A A A
}
printf("\n");
return 0;
}
2. 清零数组
#include <stdio.h>
#include <string.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
// 将数组清零
memset(arr, 0, sizeof(arr));
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]); // 输出:0 0 0 0 0
}
printf("\n");
return 0;
}
注意:
memset(arr, 0, sizeof(arr))
对于int
数组有效,因为0
的所有字节都是0
。- 但
memset(arr, -1, sizeof(arr))
不能保证arr
变为-1
,因为-1
在int
中可能是0xFFFFFFFF
(取决于 CPU 架构)。
3. 清除结构体
#include <stdio.h>
#include <string.h>
struct Data {
int a;
char b;
double c;
};
int main() {
struct Data d = {100, 'X', 3.14};
// 清零结构体
memset(&d, 0, sizeof(d));
printf("a = %d, b = %c, c = %f\n", d.a, d.b, d.c); // 输出:a = 0, b = , c = 0.000000
return 0;
}
注意:
memset
清零结构体时,所有成员的二进制值都变为0
,对于char
和int
类型有效。- 但对浮点数和指针类型,最好用
= {0}
来清零,而不是memset
,因为某些平台上memset
可能不会生成正确的0.0
或NULL
。
注意事项
1. memset
不能用于非 char
类型的初始化
memset
只能按字节填充。如果 memset(arr, 1, sizeof(arr))
作用于 int
数组:
int arr[4];
memset(arr, 1, sizeof(arr));
可能的内存布局是:
0x01010101 0x01010101 0x01010101 0x01010101
但 1
的正确表示应为 0x00000001
!
所以,memset
适用于 字符数组,但不适用于 int
、float
等非字节类型的数组。
2. memset
不能清空动态分配的内存
如果使用 malloc()
申请的内存需要清零,推荐使用:
int *p = malloc(10 * sizeof(int));
memset(p, 0, 10 * sizeof(int)); // 清零
或者直接使用:
int *p = calloc(10, sizeof(int)); // `calloc` 自动清零
小结
memset
用于填充内存,可用于清零数组、结构体等。- 适用于 字符数组、字节流等,但不适用于
int
、float
等非字节类型。 - 清零
int
数组或结构体时,最好使用= {0}
。 - 如果要初始化动态分配的内存,建议使用
calloc
。
初始化int数组时要注意的地方
使用C++的函数memset()时要注意它的操作对象是每一个字节,由于一个int变量占据的空间不只1个节所,所以不能用它将int数组初始化为0和-1之外的其他值(除非该值高字节和低字节相同)。
比如我想利用它把int型数组的每一个元素的值全部置为88是不行的,测试代码如下:
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
int bucket_size = 3;
int *bucket;
bucket = new int[bucket_size];
memset(bucket, 88, bucket_size * 4);
std::cout <<"bucket[0]的值为:"<< bucket[0] << std::endl;
return 0;
}
运行结果如下:
但因为char类型在内存中是只占一个字节的,所以是可以用函数memset()将char数组中的每一个元素置为88的,测试代码如下:
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
int bucket_size = 3;
char *bucket;
bucket = new char[bucket_size];
memset(bucket, 88, bucket_size * 1);
std::cout <<"bucket[0]的值为:"<< bucket[0] << std::endl;
return 0;
}
运行结果如下:
可见结果和刚才说的一致。