内存操作函数
内存操作函数也是在<string.h>头文件中的
四个内存函数:
memcpy(内存拷贝)
memmove(内存移动)
memcmp(内存比较)
memset(内存设置)
memcpy
void * memcpy ( void * dst, const void * src, size_t num );
函数功能:函数memcpy从src的位置开始向后复制num个字节的数据到dst的内存位置。num是字节数。
这个函数在遇到 ‘\0’ 的时候并不会停下来。不管是什么数据类型,它都能来;strcpy只能针对字符串
要保证dst有足够的容量能容纳src。
如果src和dst有任何的重叠,复制的结果都是未定义的。
实例
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 5 * sizeof(int));//拷贝5个整型进去
for (int i = 0; i < 5; i++)
{
printf("arr2[%d]=%d ,", i, arr2[i]);
}
printf("\n");
float str1[] = { 1.0f,2.0f,3.0f,4.0f };//如果不写f编译器会把他当成double类型的数据
float str2[5] = { 0.0 };
memcpy(str2, str1, 8 * sizeof(float));
for (int i = 0; i < 8; i++)
{
printf("str2[%d]=%f ,", i, str2[i]);
}
return 0;
}
memmove
void * memmove ( void* dst, const void* src, size_t num );
函数功能:memmove和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。
num是字节个数。
memmove的复制过程就好像是将src中的字节首先被复制到一个不重叠的临时数组中,然后将字节从临时数组复制到dest。
内存重叠问题
#include <stdio.h>
#include <string.h>
int main(){
int d[10]={1,2,3,4,5,6,7,8,9,10};
memcpy(d+3, d, 7*sizeof(int));// 注意第三函数为字节数
for(int i=0;i<10;i++){
printf("%d ", d[i]);
}
return 0;
}
/*输出
1 2 3 1 2 3 4 5 6 7
*/
这里的结果虽然是预期的,可能是在最新版本中解决了,但是这个是不可靠的,也就是这里可能存在问题,结果不符合预期,因为memcpy不保证内存重叠部分的正确性。所以这里应该使用memmove
memcmp
int memcmp ( const void * ptr1, const void* ptr2, size_t num );
比较从ptr1和ptr2指针开始的num个字节,注意这里的比较是每个byte逐一比较。
返回的结果=0,表示ptr1和ptr2的相等,
返回结果为>0,表示ptr1比ptr2的大,
返回结果为<0,表示ptr1比ptr2的小。
num是比较的字节的个数
void*又暗示着参数可以是任意类型
strncmp只能比较字符串的大小;而memcmp可以比较任意类型
实例
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 1,2,5,4,3 };
//在内存中的存储,小端存储模式,十六进制表示,两个数一组表示一个byte
//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00
//01 00 00 00 02 00 00 00 05 00 00 00 04 00 00 00 03 00 00 00
//int ret = memcmp(arr1, arr2, 8);//num = 8,表示8个字节的大小。这里比较数组中前两个数字。 =0
int ret = memcmp(arr1, arr2, 9);//num = 9,表示9个字节的大小。 = -2
printf("ret = %d\n", ret); //-2
return 0;
}
返回值-2表示pt1<pt2
memset
void *memset( void *dst, int c, size_t num );
将缓冲区设置为指定的字符,num是字节的个数,一个字节一个字节的改。
返回类型是一个指向存储区dst的指针
memset是一个初始化函数,作用是将某一块内存中的全部设置为指定的值。
其实c的实际范围应该在0~255,因为memset函数只能取c的后八位给所输入范围的每个字节。也就是说无论c多大只有后八位二进制是有效的。
不能任意赋值
注意memset函数是按照字节对内存块进行初始化,所以不能用它将int数组初始化为0和-1之外的其他值(除非该值高字节和低字节相同)。初始化其他值可能并不是预期的结果,请看下面这个例子
int a[] = { 1,2,3,4,5 };
memset(a, 1, 5*sizeof(int));
for (int i = 0; i < 5; i++)
printf("%d ", a[i]);
//16843009 16843009 16843009 16843009 16843009
printf("\n");
我想把数组元素全部设置为1,但实际上得到的却是非预期值
原因:
数组a是整型的,整型大小为4Byte,而memset函数是按照字节为单位进行赋值,取后8位,将1(00000001)赋给每一个字节。那么对于a[0]来说,其值为(00000001 00000001 00000001 00000001),即十进制的16843009。
-1或者0则没问题
int a[] = { 1,2,3,4,5 };
memset(a, 0, 5*sizeof(int));//0 0 0 0 0
memset(a, -1, 5*sizeof(int));//-1 -1 -1 -1 -1
for (int i = 0; i < 5; i++)
printf("%d ", a[i]);
return 0;
字符数组也没问题,因为memset是按1byte来修改的
char a[5];
memset(a, 'd', 5); //d d d d d
for (int i = 0; i < 5; i++)
printf("%c ", a[i]);
return 0;
https://blog.csdn.net/weixin_44162361/article/details/115790452
参考资料
https://blog.csdn.net/m0_68814541/article/details/127334335
https://blog.csdn.net/weixin_56810796/article/details/128308824