
🔥个人主页:艾莉丝努力练剑 🍓专栏传送门:《C语言》 🍉学习方向:C/C++方向 ⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平

前言:前面几篇文章介绍了c语言的一些知识,包括循环、数组、函数、VS实用调试技巧、函数递归、操作符、指针、字符函数和字符串函数、结构体、联合和枚举、动态内存管理、文件操作、编译和链接、预处理等,在这篇文章中,我将开始介绍C语言内存函数的一些重要知识点!对C语言内存函数感兴趣的友友们可以在评论区一起交流学习!
memcmp:memory copy——内存拷贝;

代码原型:
void* memcpy(void* destination, const void* source, size_t num);三板斧——
功能: (1)memcpy 是完成内存块拷贝的,不关注内存中存放的数据是什么; (2)函数 memcpy 从 source 的位置开始向后复制 num 个字节的数据到 destination 指向的内存 位置; (3)如果 source 和 destination 有任何的重叠,复制的结果都是未定义的 (内存重叠的情况使用memmove 就行)。 注: memcpy 的使用需要包含 <string.h>。 参数: destination :指针,指向目标空间,拷贝的数据存放在这里; source :指针,指向源空间,要拷贝的数据从这里来; num :要拷贝的数据占据的字节数。 返回值: 拷贝完成后,返回目标空间的起始地址。
strcpy、strncpy拷贝字符串的,是有局限性的; 拷贝一个整型数组呢?结构体数组呢?
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
// 0 1 2 3 4 5...
int arr2[20] = { 0 };
// 0 1 2 3 4 5...
//想把arr1中的10个整数,拷贝到arr2中
//循环遍历
//memcpy
memcpy(arr2, arr1, 40);
return 0;
}#include<stdio.h>
int main()
{
int arr1[] = { 1.2f,2.2f,3.2f,4.5f,5.5f };
int arr2[20] = { 0 };
memcpy(arr2, arr1, 5 * sizeof(float));
return 0;
}#include<stdio.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;
src = (char*)src + 1;
dest = (char*)dest + 1;
}
return ret;
}
//4*3 + 3
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
my_memcpy(arr2, arr1, 40);
return 0;
}那么我们可不可以把1,2,3,4,5这五个整型拷贝到3,4,5,6,7这五个整型的位置(覆盖了):
下面是我们自己写的代码演示:
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;
src = (char*)src + 1;
dest = (char*)dest + 1;
}
return ret;
}
//4*3 + 3
int main()
{
//int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
//int arr2[20] = { 0 };
//my_memcpy(arr2, arr1, 40);
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memcpy(arr + 2, arr, 20);
return 0;
}我们发现达不到我们想要的效果。
那索性就不要用my_memcpy了,下面是我们直接调用库里的函数实现的:
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;
src = (char*)src + 1;
dest = (char*)dest + 1;
}
return ret;
}
//4*3 + 3
int main()
{
//int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
//int arr2[20] = { 0 };
//my_memcpy(arr2, arr1, 40);
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
memcpy(arr + 2, arr, 20);
return 0;
}监视打开:


memcpy:不重叠的就可以了,memcpy连重叠的都能搞定。
memmove:可以处理不重叠的,也可以处理重叠内存。

代码原型:
void* memmove(void* destination, const void* source, size_t num);三板斧——
功能: (1)memmove函数也是完成内存块拷贝的; (2)和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。 注: memmove的使用也需要包含<string.h>。 参数: destination :指针,指向目标空间,拷贝的数据存放在这里; source :指针,指向源空间,要拷贝的数据从这里来; num :要拷贝的数据占据的字节数。 返回值: 拷贝完成后,返回目标空间的起始地址。
#include<stdio.h>
#include<assert.h>
int main()
{
//内存没有重叠
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
//memcpy();
memmove(arr2, arr1, 20);
}#include<stdio.h>
#include<assert.h>
int main()
{
//内存重叠
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr + 2, arr, 20);
return 0;
}#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
void * my_memmove(void* dest,void* src,size_t num)
{
assert(dest && src);
void* net = dest;
if (dest < src)
{
//前->后
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else//2 3
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return net;
}
int main()
{
//内存重叠
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr + 2, arr, 20);
return 0;
}
代码原型:
void* memset(void* ptr, int value, size_t num);三板斧——
功能: memset 函数是用来设置内存块的内容的,将内存中指定长度的空间设置为特定的内容。 注: memset 的使用也需要包含 <string.h>。 参数: ptr :指针,指向要设置的内存空间,也就是存放了要设置的内存空间的起始地址; value :要设置的值,函数将会把 value 值转换成 unsigned char 的数据进行设置的,也就是以字节为单位来设置内存块的; num :要设置的内存长度,单位是字节。 返回值:返回的是要设置的内存空间的起始地址。
//针对字符数组
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "hello world";
memset(arr + 2, 'x', 5);
printf("%s\n", arr);
return 0;
}#include<stdio.h>
#include<string.h>
int main()
{
int arr[10] = { 0 };
//能否将arr的每个元素设置为1
memset(arr, 1, 40);
return 0;
}当有一块内存空间需要设置内容的时候,就可以使用memset函数,值得注意的是memset函数对内存单元的设置是以字节为单位的。

代码原型:
int memcmp(const void* ptr1, const void* ptr2, size_t num);三板斧——
功能: 比较指定的两块内存块的内容,比较从ptr1和ptr2指针指向的位置开始,向后的num个字节。 注:memcmp 的使用需要包含 <string.h>。 参数: ptr1 :指针,指向一块待比较的内存块; ptr2 :指针,指向另外⼀块待比较的内存块; num :指定的比较长度,单位是字节。 返回值:

#include<stdio.h>
#include<string.h>
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, 16);
if (r > 0)
printf(">\n");
else if (r < 0)
printf("<\n");
else
printf("==\n");
return 0;
}打开内存,观察一下:

输出结果:

#include<stdio.h>
#include<string.h>
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");
else
printf("==\n");
return 0;
}打开内存,观察一下:

输出结果:

(1)如果要比较2块内存单元的数据的大小,可以使用 memcmp 函数,这个函数的特点就是可以指定比较长度; (2)memcmp 函数是通过返回值告知大小关系的。
往期回顾:
字符函数和字符串函数(二):strncpy、strncat、strncmp函数的使用、strstr的使用和模拟实现、strtok函数的使用、strerror函数的使用
字符函数和字符串函数(一):字符分类函数、字符转换函数、strlen的使用和模拟实现、strcpy的使用和模拟实现、strcat的使用和模拟实现、strcmp的使用和模拟实现
C语言指针深入详解(六):sizeof和strlen的对比,【题解】数组和指针笔试题解析、指针运算笔试题解析
结语:本篇文章就到此结束了,本文为友友们分享了C语言内存函数相关的一些重要知识点,如果友友们有补充的话欢迎在评论区留言,在这里感谢友友们的关注与支持!