这次介绍一个库函数memset的使用方法以及我对其的思考,请各位朋友耐心看完。
函数介绍
首先在使用之前,要包含一个头文件<string.h>,顾名思义,这是个与字符相关的库函数。
接下来就是其功能、参数、和返回值,如图:(翻译可能有些误差,英文好的老铁可以直接看第一张图)
这里我们就可以大致知道其功能就是:将指针指向的那块内存中的前num个字节的内容设置为我们想要的值。
函数使用
在char类型的数组中,一个字符所占的空间为一个字节,那么就可以将其前num个字符改成指定的值。
这里我们将指针ptr设为首元素地址arr,要设置的值value为'*',设置的字节数为5个字节,也就是5个字符的空间;可以看到,结果将"Hello"成功改为了"*****"。
这里我们突发奇想,能不能对整形数组使用memset呢?实践出真知,接下来就来举例,对一个整形数组int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }使用memset。
1.将其第一个元素的1设置为2。
因为整数在内存中是以二进制的形式存储的,int 型1 的二进制补码序列为000000000000000000000001,这里我们就可以把第一个字节中的1改为2,于是将指针ptr设为首元素地址arr,value设为2,num设为1。
这里可以看出成功了。
2.将其第一个元素设置为256。
这时我们要注意一个字节为8个比特位,最大能存储的值为11111111(二进制),也就是255,而256的无符号二进制序列为100000000,这时候我们发现超出一个字节空间的最大容量,预期修改的第一个元素的最终值的二进制序列为00000000000000000000000100000000,也就是256。
这里我们看到并没有像预期那样将1改成256。猜想原因在于value参数虽然是int类型的,但是在填充内存块之前要先转换为unsigned char 类型的值再进行填充,也就是先将256转换为unsigned char 类型,因为超出了最大值,所以会发生截断
于是便把多出来的1丢了,所以其转换为unsigned char 类型的值为0,即用0填充,所以第一个元素的二进制序列为00000000000000000000000000000000,也就是0。
那么知道了这个条件以后,就能不能正确赋值了呢?
3.一个整形数组中的一个元素占四个字节的大小,我们就不像上面一样先研究其的二进制序列了,直接将空间大小设为4个字节,对它进行整体赋值。
可是最终的结果却是这样,为什么呢,我们来内存中找答案。
在VS编译器上,为了方便显示,采用16进制表示,但在内存中本质还是以二进制形式存储的(不了解整数在内存中存储的可以看我上一期的博客),红框中就是数组arr的空间,一行为一个元素的空间。调用memset后, 第一个元素的内存空间的值如图,
这里就引发了思考,为什么会这样,每个字节的内容都被改成了1,原来memset 是以字节为单位对内存进行设值的,也就是说,有n个字节的空间,memset 不是将这个空间作为整体进行赋值,而是以1个字节为单位,分别对n个空间进行赋值。
所以要对整形数组进行设值时,就只能设置0或者-1,因为它们转化成unsigned char 类型时的二进制序列分别为00000000、11111111,对每个字节分别赋值后的二进制序列分别为32个0,和32个1。正好就是0和-1。
最后,这里并不建议大家对非字符数组使用memset,如果使用不恰当,你就掉坑里去了。
好了,以上就是全部内容,感谢大家的阅读。