织梦 网站统计,响应式网站滑动,快云助手网站建设视频教程,陕西建设网官网appC语言之内存函数 文章目录 C语言之内存函数1. memcpy 使⽤和模拟实现1.1 memcpy 函数的使用1.3 memcpy的模拟实现 2. memmove 使⽤和模拟实现2.1 memmove 函数的使用2.2 memmove的模拟实现 3. memset 函数的使用4. memcmp 函数的使⽤ 1. memcpy 使⽤和模拟实现
函数声明如下
void * memcpy ( void * destination, const void * source, size_t num );memcpy函数和strncpy函数很相似
只不过strncpy函数只能处理字符数组而memcpy函数可以处理任意类型的数据strncpy函数会在目标字符数组结尾添加’\0’而memcpy函数则不会都在string.h库函数中
1.1 memcpy 函数的使用
代码一 将arr1中的1 2 3 4 5 拷贝到arr2中
#include stdio.h
#include string.h
int main()
{int arr1[] { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] { 0 };memcpy(arr2, arr1, 5*sizeof(int));int i 0;for (i 0; i 10; i){printf(%d , arr2[i]);}return 0;
}代码运行结果如下
memcpy函数有三个参数
参数一为需要拷贝的目标地址参数二为拷贝数据来源的地址参数三为需要拷贝的字节大小 在上述代码中传给了memcpy函数20个字节的大小 因为整型是4个字节所以只会拷贝前5个数据
代码二 将arr1中的4 5 6 7 8拷贝到arr2中
#include stdio.h
#include string.h
int main()
{int arr1[] { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] { 0 };memcpy(arr2, arr13, 5*sizeof(int));int i 0;for (i 0; i 10; i){printf(%d , arr2[i]);}return 0;
}代码三 将arr1中的字符串拷贝到arr2中
#include stdio.h
#include string.h
int main()
{char arr1[] Hello \0World!;char arr2[20] { 0 };memcpy(arr2, arr1, 13);int i 0;for (i 0; i 13; i){printf(%c, arr2[i]);}return 0;
}代码运行结果如下 memcpy函数在拷贝数据时遇到\0时不会停下来
代码四 将arr中的 1 2 3 4 5 拷贝到arr中4 5 6 7 8的位置上
#include stdio.h
#include string.h
int main()
{int arr[] { 1,2,3,4,5,6,7,8,9,10 };memcpy(arr 3, arr, 5 * sizeof(int));int i 0;for (i 0; i 10; i){printf(%d , arr[i]);}return 0;
}由于空间重叠了当改dest的第三个元素时src的第三个元素已经被改成了1使用dest第三个元素为1第四个同理为2所以使用memcpy无法拷贝重复的空间
在VS2022中可以实现 但是 C语言中规定 memcpy拷贝的就是不重复的数据 重复的数据交给memmove
在VS2022中memcpy是可以拷贝重复部分的数据的在C语言中规定的memcpy功能可能只有60分但是VS2022中可能将其提升到了100分
总结 • 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。 • 这个函数在遇到 ‘\0’ 的时候并不会停下来。 • 如果source和destination有任何的重叠复制的结果都是未定义的
1.3 memcpy的模拟实现
void *memcpy(void *dest, const void *src, size_t n);思路
由于memcpy要处理不同类型的数据所以第一个参数和第二个参数得是void类型的void类型的指针可以接收任意类型的地址由于不确定传进来的是什么数据只知道需要拷贝多少字节在函数内部可以将其强制类型转换为char*类型的指针一个字节一个字节拷贝函数返回值为dest的地址所以为void*
实现代码如下
#include stdio.h
#include assert.hvoid* my_memcpy(void* dest, const void* src, size_t num)
{char* ret dest;assert(dest src); //assert断言判断传入的地址是否为空指针while (num--) //一个字节一个字节拷贝{*(char*)dest *(char*)src; //void*类型不能解引用并且需要一个字节一个字节的拷贝所以强制类型转换为char*类型dest (char*)dest 1; //强制类型转换是临时的再次强制类型转换并1找到下一个需要交换的地址src (char*)src 1;}return ret; //返回dest的地址
}int main()
{int arr1[] { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] { 0 };my_memcpy(arr2, arr1, 5 * sizeof(int));int i 0;for (i 0; i 10; i){printf(%d , arr2[i]);}return 0;
2. memmove 使⽤和模拟实现
函数声明如下
void * memmove ( void * destination, const void * source, size_t num );• 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的
• 如果源空间和⽬标空间出现重叠就得使⽤memmove函数处理。
2.1 memmove 函数的使用
将arr中的 1 2 3 4 5 拷贝到arr中4 5 6 7 8的位置上
#include stdio.h
#include string.h
int main()
{int arr[] { 1,2,3,4,5,6,7,8,9,10 };memcpy(arr 3, arr, 5 * sizeof(int));int i 0;for (i 0; i 10; i){printf(%d , arr[i]);}return 0;
}代码运行结果如下
2.2 memmove的模拟实现
void * memmove ( void * destination, const void * source, size_t num );思路
由于memmove也要处理不同类型的数据所以第一个参数和第二个参数得是void类型的void类型的指针可以接收任意类型的地址由于不确定传进来的是什么数据只知道需要拷贝多少字节在函数内部可以将其强制类型转换为char*类型的指针一个字节一个字节拷贝函数返回值为dest的地址所以为void*dest 和 src 会有两种关系 1.dest 在 src 左边 2.dest 在 src 右边
情况一
上述情况虽然有重叠的空间但是还是可以拷贝实现方式和memcpy一样
情况二 在上述代码中出现了重叠的空间如果正序交换的话后面的内容被覆盖了无法交换所以我们换种方式交换逆序交换 这样交换内容就不会被覆盖了
实现代码如下
#include stdio.h
#include assert.h
void* my_memcpy(char* dest, const char* src, size_t num)
{char* ret dest; assert(dest src); //assert断言if (dest src) //当dest在src左边时{while(num--) //逻辑和memcpy一致{*(char*)dest *(char*)src;dest (char*)dest 1;src (char*)src 1;}}else //dest在src右边{while (num--) //一个字节一个字节拷贝{*((char*)dest num) *((char*)src num); //找到最后一个字节然后拷贝 num--之后找到倒数第二个字节拷贝}}
}
int main()
{int arr[] { 1,2,3,4,5,6,7,8,9,10 };my_memcpy(arr 3, arr, 5 * sizeof(int));int i 0;for (i 0; i 10; i){printf(%d , arr[i]);}return 0;
}3. memset 函数的使用
函数声明如下
void * memset ( void * ptr, int value, size_t num );memset是⽤来设置内存的将内存中的值以字节为单位设置成想要的内容 第一个参数是需要修改的地址 第二个参数是设置成什么内容 第三个参数是要设置的大小
#include stdio.h
#include string.h
int main()
{char arr[] abcdefghi;memset(arr, x, 5);printf(%s\n, arr);return 0;
}代码运行结果 xxxxxfghi
将前5个字节的元素改成了x
4. memcmp 函数的使⽤
函数声明如下
int memcmp ( const void * ptr1, const void * ptr2, size_t num );和strncmp相似 都是⽐较从ptr1和ptr2指针指向的位置开始向后的num个字节 返回值如下 如果ptr1大于ptr2则返回一个大于零的值 如果ptr1小于ptr2则返回一个小于零的值 如果ptr1等于ptr2则返回一个零
#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,9 };int ret memcmp(arr1, arr2, 16);if (ret 0)printf(大于\n);else if (ret 0)printf(小于);elseprintf(等于\n);return 0;
}代码运行结果 等于