【C语言入门级教学】内存函数
文章目录
- 1.memcpy使⽤和模拟实现
- 2.memmove使⽤和模拟实现
- 3.memset函数的使⽤和模拟实现
- 4.memcmp函数的使⽤和模拟实现
1.memcpy使⽤和模拟实现
void * memcpy ( void * destination, const void * source, size_t num );//可以拷贝许多类型的数据,所以数据地址类型是void*
功能
• 从源头指向的内存块拷贝固定字节数的数据到目标指向的内存块
• memcpy:memory copy(内存拷贝)
• 要包含头文件==<string.h>==
• 与strcpy函数不同的点:这个函数在遇到 ‘\0’ 的时候并不会停下来,总是精确地拷贝参数传入的字节数
• 如果source和destination有任何的重叠,复制的结果都是未定义的。
参数
destination:指针,指向目标空间,拷贝的数据存放在这里
source:指针,指向源空间,要拷贝的数据从这里来
num:要拷贝的数据占据的字节数
返回值
函数运行结束后返回拷贝后的目的地内存块的起始地址
#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, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr2[i]); } return 0;}
//或者
int main()
{float arr1[]={1.2f,2.2f,3.2f,4.2f,5.5f};float arr2[10]={0};
// memcpy(arr2,arr1,20);memcpy(arr2,arr1,5*sizeof(float));//忘记浮点数的字节数可以这样做return 0;
}
有个题外话:float型无法精确保存数据
memcpy函数的模拟实现:
void * memcpy ( void * dest, const void * src, size_t num)
{ void * ret = dest; assert(dest); assert(src); while (num--) { *(char *)dest = *(char *)src;//转换成char*可以一个字节一个字节赋值,但是是临时转换//如果转换为整型,只能四个字节四个字节赋值src=(char*)src+1;//需要再重新转换成char*dest=(char*)dest+1;//不能写成//*(char*)dest++=*(char*)src++;//因为dest和src会先转换成char*,但是++操作会给dest和src++,而不是给(char*)dest和(char*)src进行++操作} return ret;
}
[注意]
void*不能进行++操作,因为void *是一个指向未知类型的指针类型,它的大小是不确定的。而++操作需要知道指针所指向的对象的大小,才能正确的进行指针运算。
如果出现下段这种代码:
#include<stdio.h>
#include<string.h>
int main()
{ int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; memcpy(arr1+2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); }return 0;
}
//输出结果却是1 2 1 2 1 2 1
分析:因为目标空间和源头空间重复,给arr[4]拷贝时arr[2]已经被拷贝为1了,所以arr[4]会被拷贝现在arr[2]的值,那怎么解决这个问题呢,可以用memmove函数(但是vs编译器的memcpy可以拷贝重叠空间,属于超额完成任务)
2.memmove使⽤和模拟实现
void * memmove ( void * destination, const void * source, size_t num );//和memcpy参数一样
功能
• memmove函数也是完成内存拷贝的
• memmove函数处理的源内存块和⽬标内存块是可以重叠,也可以不重叠。
• 需要包含头文件==<string.h>==
参数
destination:指针,指向目标空间,拷贝的数据存放在这里
source:指针,指向源空间,要拷贝的数据从这里来
num:要拷贝的数据占据的字节数
返回值
函数运行结束后,返回目标空间的起始地址
#include<stdio.h>
#include<string.h>
int main()
{ int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; memmove(arr1+2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); }return 0;
}
输出的结果: 1 2 1 2 3 4 5 8 9 10
memmove的模拟实现:
第二种方法
#include<stdio.h>
#include<assert.h>
void* my_memmove ( void * dest, const void * src, size_t num)
{ assert(dest&&src);void* ret=dest;//先存起来if(dest>src){while(num--){ *(char*)dest=*(char*)src;dest=(char*)dest+1;src=(char*)src+1;}}else{while(num--){*((char*)dest+num)=*((char*)src+num);}}return ret;//与memmove函数保持一致
}
int main()
{ int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; my_memmove(arr1+2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); }return 0;
}
第一种方法
#include<stdio.h>
#include<assert.h>
void * memmove ( void * dest, const void * src, size_t count)
{assert(dest&&src);void * ret = dst;if (dest <= src || (char *)dest >= ((char *)src + count)) {while (count--) {*(char *)dest = *(char *)src;dest = (char *)dest + 1;src = (char *)src + 1;}}else {dest = (char *)dest + count - 1;src = (char *)src + count - 1;while (count--) {*(char *)dest = *(char *)src;dest = (char *)dest - 1;src = (char *)src - 1;}}return(ret);
}
int main()
{ int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; my_memmove(arr1+2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); }return 0;
}
3.memset函数的使⽤和模拟实现
void * memset ( void * ptr, int value, size_t num );
功能
• memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。
• 需包含头文件==<string.h>==
参数
ptr:指针,指向要设置的内存空间,存放了要设置的内存空间的起始地址
value:要设置的值,函数将会把value值转换成unsigned char的数据进行设置的,也就是以字节为单位来设置内存块的
num:要设置的内存长度,单位是字节
返回值
函数运行完之后返回要设置的内存空间的起始位置
#include<stdio.h>
#include<string.h>
int main ()
{ char str[] = "hello world"; memset (str,'x',6); printf(str); return 0;
}
输出的结果: xxxxxxworld
[注意]
memset函数对内存单元的设置是以字节为单位的
int main()
{int arr[10]={0};memset(arr,1,40);return 0;
}
结果如下:发现每个字节都设置为1,而不是00 00 00 01
4.memcmp函数的使⽤和模拟实现
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
功能
• ⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节
• 需包含头文件==<string.h>==
参数
ptr1:指针,指向一块待比较的内存块
ptr2:指针,指向另外一块待比较的内存块
num:指定的比较长度,单位是字节
返回值
示例一:
int main()
{int arr1[]={1,2,3,4,5,6,7,8,9,10};int arr2[]={1,2,3,4,8};int r=memcmp(arr1,arr2,17);if(r>0)printf(">\n");else if(r<0)printf("<\n");elseprintf("=\n");return 0;
}
示例二:
#include<stdio.h>
#include<string.h>
int main()
{ char buffer1[] = "DWgaOtP12df0"; char buffer2[] = "DWGAOTP12DF0"; int n; n = memcmp(buffer1, buffer2, sizeof(buffer1)); if (n > 0) printf("'%s' is greater than '%s'.\n", buffer1, buffer2); else if (n < 0) printf("'%s' is less than '%s'.\n", buffer1, buffer2); else printf("'%s' is the same as '%s'.\n", buffer1, buffer2); return 0;
}