memset

本文详细解析了memset函数的工作原理及其使用注意事项,特别强调了在处理不同数据类型时的正确使用方法。

综述

首先,memset是一个比较*疼的东西,主要原因是它当初被设计出来主要是用来为字符串(比如char型数组)赋值的,但是当大家把它拿来给其他类型(比如int,double等)赋值的话,就该*疼了——

头文件与函数原型

之所以说memset用来处理字符串,可以行它的头文件略见一斑

string.h

这显然是来处理字符串的啊。

void * memset (void * p,int c,size_t n);

由原型可以看出:指针p为所操作的内存空间的首地址,c为每个字节所赋的值,n为所操作内存空间的字节长度,也就是内存被赋值为c的字节数。

举例及注意事项

下面问题来了,memset究竟要注意什么?

举个例子:

char a[10];
memset(a, '\n', 10);
这个例子说明了将一个10个字节的char型数组全部赋值为10个'\n',这当然可以,因为memset本来就是处理字符或字符串的。


问题是如果处理其他类型呢?

再举个例子:

int a[10];
memset(a, 1, 10);

结果是什么呢?是将10个int型的数组a全部赋值为整数1吗?显然不是的。

我们不妨从底层来看:一个int有4个字节,也就是说数组a其实是一个连续40个字节的存储空间。而memset(a, 1, 10)代表将10个字节赋值为1,也就是说a[0] = a[1] = 0x01010101,a[2] = 0x01010000,a[3] = a[4] = ... = a[9] = 0。

所以,赋值显然是失败的。失败的根源就是memset本来就是用来处理字符,按照字节来操作的,所以对其他类型的数据操作一定要慎重!


不过初始化(赋0值)int型数组倒是可以的:

int a[10];
memset(a, 1, 10*sizeof(int));

号外

对赋值的理解:

<span style="font-size:18px;">char c = 1;</span>

对于上面的代码,我们可以这样理解——

(1)从实际内存操作上看,上面的代码表示对c代表的字节赋1;

(2)从逻辑内容上看,上面的代码表示将c赋值为ASCII值1所代表的字符。


int m = 7;
int n = 8;
int i;

int **a;	//用malloc申请建立二维数组

a = (int **) malloc(m * sizeof(int *));

for(i=0; i<m; ++i)
    a[i] = (int *) malloc(n * sizeof(int));


memset(a, 0, sizeof(int) * m * n);	//wrong!!!


此时对二维数组初始化赋值为0是不对的,因为用这种方式申请出来的二维数组不是连续的。(准确的说这是 存放有指向一维int型数组的指针的一维int*型数组)


但是

int a[7][8];
memset(a, 0, 7*8*sizeof(int));
对这种定义的二维数组是可以的。因为这种申请方式保证了数组内存地址是连续的。

号外(临时补充内容):

<span style="font-size:18px;">char c = 1;</span>

对于上面的代码,我们可以这样理解——

(1)从实际内存操作上看,上面的代码表示对c代表的字节赋1;

(2)从逻辑内容上看,上面的代码表示将c赋值为ASCII值1所代表的字符。

### C/C++ 中 `memset` 函数的使用 `memset` 是一个用于操作内存块的标准库函数,在 C 和 C++ 编程语言中广泛应用于初始化数组或结构体。它位于头文件 `<cstring>` 或 `<string.h>` 中[^1]。 #### 基本语法 以下是 `memset` 的基本定义: ```c void* memset(void* ptr, int value, size_t num); ``` - **参数说明** - `ptr`: 指向要填充的内存区域的指针。 - `value`: 要设置的值,该值会被转换为无符号字符(unsigned char)并写入到目标内存中。 - `num`: 需要被设置的字节数。 返回值是一个指向已修改内存块的指针,其类型为 `void*`,因此可以安全地强制转换为目标类型的指针[^2]。 #### 使用场景 通常情况下,`memset` 可以用来快速清零一段连续的内存空间或者给整个数据结构赋相同的初始值。例如: ##### 初始化整型数组为0 ```cpp #include <iostream> #include <cstring> // 包含 memset 定义 int main() { int array[5]; std::memset(array, 0, sizeof(array)); // 将数组全部置为0 for (size_t i = 0; i < 5; ++i) { std::cout << array[i] << ' '; } } ``` 上述代码会输出五个0,因为每个字节都被设为了0[^3]。 需要注意的是,当尝试通过 `memset` 设置非单字节数值时可能会引发未定义行为。比如试图用 `-1` 来表示负数可能不会按预期工作,因为它实际上只是把每一个单独的字节都填成了二进制形式下的全1位模式[^4]。 #### 结构体成员变量统一初始化 对于复杂的数据类型如自定义结构体也可以利用此特性来简化构造过程: ```cpp struct ExampleStruct { int a; double b; }; ExampleStruct example; std::memset(&example, 0, sizeof(ExampleStruct)); // 此处将 struct 所有字段均重置为其对应类型的默认状态 ``` 尽管如此,现代C++提倡更安全的方式来进行对象初始化,例如直接列表初始化或是采用标准容器类提供的接口方法替代手动调用低级API[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值