目录
- void* memcpy(void* destination, const void* source,size_t num);
- //传参后使用void*接收,说明这个函数不论是什么类型都会执行。
size_t表示无符号数字
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
这个函数在遇到'\0'的时候并不会停下来。
如果source和destination有任何的重叠,复制的结果都是未定义的。
- int main()
- {
- int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
- int arr2[10] = { 0 };
- memcpy(arr2, arr, 20);
-
- return 0;
- }
- int main()
- {
- float arr1[] = { 1.0f,2.0f,3.0f,4.0f };//数值后加f表示该数为浮点数
- float arr2[5] = { 0 };
- memcpy(arr2, arr1, 8);
-
- return 0;
- }
- //这种写法不是最好的写发,有些编译器是编不过去的
- #include
- void* my_memcpy(void* destination, const void* source,size_t num)
- {
- assert(destination);
- assert(source);
- void* ret = destination;
- for (int i = 0; i < num; i++)
- {
- *((char*)destination)++ = *((char*)source)++;
- }
- return ret;
- }
-
- //这种方法可以在所以编译器中使用
- void my_memcpy(void* destination, const void* source,size_t num)
- {
- assert(destination);
- assert(source);
- void* ret = destination;
- while(num--)
- {
- *(char*)destination = *(char*)source;
- destination = (char*)destination + 1;
- source = (char*)source + 1;
- }
- return ret;
- }
例如使用下面的代码传递:
- int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
- my_memcpy(arr+2, arr, 20);
内存展示为:
而编译器定义的memcpy函数却不是这样定义的,memcpy的结果为:
这并不是说之前写的模拟函数有问题,在这里我们需要明白一点,在C语言规定中,那段错误的结果才是memcpy真实的结果,但我使用的是VS编译器,由于编译器的不同,它将memcpy改的更为强大了而已,其它编译器并非如此。
在C语言规定中,当拷贝的两组数地址部分重合时,应该使用memmove函数,memmove函数的功能是强于memcpy的,接下来讨论的编译过程也是属于memmove的但在VS编译器当中两者差异不大,这里以C语言规定为准,但大家在平时练习的时候需要注意这一点。
void* memmove(void* destination,const void* source,size_num);
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。
当拷贝的两组数出现重叠时,让我们看看memmove函数是如何处理的。
这个时候我们就要分类讨论了:
des == destination
sou == source
num == 20;
此时des和sou分别是destination和source所表示的地址
- void* my_memmove(void* destination, const void* source, size_t num)
- {
- void* tem = destination;
- if (destination < source)
- {
- for (int i = 0; i < num; i++)
- {
- *(char*)destination = *(char*)source;
- destination = (char*)destination + 1;
- source = (char*)source + 1;
- }
- }
- else
- {
- destination = (char*)destination + num - 1;
- source = (char*)source + num - 1;
- for (int i = 0; i < num; i++)
- {
- *(char*)destination = *(char*)source;
- destination = (char*)destination - 1;
- source = (char*)source - 1;
- }
- }
- return tem;
- }
- 此函数目前我见到使用最多的场景是用来初始化一块连续的空间(可以看作数组)。
在第一次完成这篇博客时,我没想着把这个函数加入其中,我感觉它不是很重要,在今天做题的时候,勾起我对这个memset复杂的回忆。
之前做题时,创建数组后初始化都是进行循环一个个初始化,一次看题解不经意的一瞥,注意到这个函数,用了以后感觉是真香。但毕竟做题少而且平时练习的时候都是直接给数组初始化为0,不像做题的时要自己malloc一个新的空间。
void* memset(void* ptr,int value,size_t num);
- int main()
- {
- int arr1[] = { 1,2,3,4,5 };
-
- memset(arr1, 9, 8);
-
- return 0;
- }
arr1数组最开始的内存:
memset后:
- int main()
- {
- int* arr = (int*)malloc(sizeof(int) * 5);//开创了5个int大小的空间
- memset(arr, 0, 20);
-
- return 0;
- }
memset前:
memset后: