本篇文章将介绍C语言中的内存函数的用法以及模拟实现,大家快搬好小板凳来听讲啦~
要介绍的内存操作函数有以下四种:
- memcpy
- memmove
- memset
- memcmp
1、memcpy
· 这个函数的功能是在缓存区之间复制字符(此字符不仅局限于char型的数据),怎么来理解呢?
· 通俗地讲,就是将缓存区的一部分数据复制到另一块地方去,跟字符串函数strcpy很想,只不过,memcpy的功能更加强大,可以对不同类型的数据进行操作。
· 话不多说,上操作!
#include<stdio.h>
#include<memory.h>
//#include<string.h>
//想要使用memcpy需要包含以上两个头文件的至少一个
int main()
{
//使用内存函数
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr2[] = {12, 23, 34, 45, 56};
memcpy(arr1, arr2, 20);//将arr2里面前20个字节的内容复制到arr1中
//打印数组arr1
int i = 0;
int sz = sizeof(arr1) / sizeof(arr1[0]);
for (i = 0; i < sz; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
以上是使用内存函数的实例代码,运行结果如下图
· 先解释一下memcpy的使用,
void *memcpy( void *dest, const void *src, size_t count );//memcpy的定义
· 传入两个数组的地址,定义的是void*类型,这就是为什么memcpy可以处理多种类型数据的原因,只要在函数内部进行强制转换就ok,count是要进行操作的字节数,因为int是4个字节,所有20就是操作5个int元素。
· 知道了函数的使用和实现的功能,接下来咱就来自己模拟一下
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, void* src, size_t count)
{
assert(dest && src);//断言dest和src不是空指针,因为空指针解引用是非法的
void* ret = dest;//函数返回的是目标数组的首元素地址,因为接下来dest会发生变化,所有提前定义变量存储dest的地址
while (count--)
{
*((char*)dest) = *((char*)src);//强制转换为char*类型数据,进行一个字节一个字节的修改
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr2[] = { 12, 23, 34, 45, 56 };
my_memcpy(arr1, arr2, 20);
int i = 0;
int sz = sizeof(arr1) / sizeof(arr1[0]);
for (i = 0; i < sz; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
·模拟的想法是很简单的,只要进行一个字节一个字节的访问,然后依次赋值就好啦~
2、memmove
· memmove函数实际上是对memcpy函数的进一步优化,使得函数操作的对象可以是同一个数组
上操作!
#include<stdio.h>
#include<string.h>//使用memmove需要引用的头文件
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
memmove(arr + 3, arr, 20);
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
· 以上是使用内存函数的实例代码,运行结果如下图
· memmove的参数设置和memcpy相同,只是内部函数实现有所不同
· 接下来我们自己上手实现以下,来发现memmove与memcpy有什么不一样~
#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, void* src, size_t count)
{
assert(dest && src);
void* ret = dest;
if (dest < src)//如果dest的地址低于src,数组从前往后进行赋值不会造成数据的提前覆盖
{
while (count--)
{
*((char*)dest) = *((char*)src);
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (count--)//如果dest的地址高于src,数组从后往前进行赋值不会造成数据的提前覆盖,用count来控制数组从最后往前一次赋值,dest和src就不用进行变化了
{
*((char*)dest + count) = *((char*)src + count);
}
}
return ret;
}
//思想依然是一个字节一个字节的访问,只不过对dest和src的地址高低进行了判断
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
my_memmove(arr + 3, arr, 20);
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
3、memset
·这个函数的功能是将缓冲区的数据设定为指定字符
· 干巴巴的文字说明看着头痛,直接上操作!
#include <stdio.h>
#include <memory.h>
int main()
{
char buffer[] = "This is a test of the memset function";
printf("Before: %s\n", buffer);
memset(buffer, '*', 4);
printf("After: %s\n", buffer);
return 0;
}
· 以上是使用内存函数的实例代码,运行结果如下图
·解释一下函数的使用
void *memset( void *dest, int c, size_t count );
· 传入要修改的数组的首地址,要修改成的数据(传入char的话就是传入它的ANSII码),操作的字节数,还是很好理解的
· 接下来,咱就继续上手模拟
#include<stdio.h>
#include<assert.h>
void* my_memset(void* dest, int c, size_t count)
{
assert(dest);
void* ret = dest;
while (count--)
{
*((char*)dest) = c;
dest = (char*)dest + 1;
}
return ret;
}
int main()
{
char buffer[] = "This is a test of the memset function";
printf("Before: %s\n", buffer);
my_memset(buffer, '*', 4);
printf("After: %s\n", buffer);
return 0;
}
· 这个函数的模拟相较于上两个函数更加简单~
4、memcmp
· 这个函数跟strcmp就非常相似了,不过比较的数据类型范围更广
· 上操作~
#include <string.h>
#include <stdio.h>
int main()
{
int arr1[10] = { 1,2,3,4,5,5,6,7,8,9 };
int arr2[10] = { 1,2,3,4,5,6,7,8,9,10 };
int ret = memcmp(arr1, arr2, 40);
if (ret > 0)
{
printf("arr1数组里的数大于arr2数组里的数\n");
}
else
if(ret==0)
{
printf("arr1数组里的数等于arr2数组里的数\n");
}
else
{
printf("arr1数组里的数小于arr2数组里的数\n");
}
return 0;
}
· 以上是使用内存函数的实例代码,运行结果如下图
· 此函数的定义为
int memcmp( const void *buf1, const void *buf2, size_t count );
· 传入两个相比较数组的首元素地址,再传入要比较的字节数,然后返回一个int类型的数据
· 模拟走起!
#include<stdio.h>
#include<assert.h>
int my_memcmp(const void* buf1, const void* buf2, size_t count)
{
assert(buf1 && buf2);
while ((*(char*)buf1 == *(char*)buf2) && count)
{
count--;
buf1 = (char*)buf1 + 1;
buf2 = (char*)buf2 + 1;
}
return (*(char*)buf1 - *(char*)buf2);
}
int main()
{
int arr1[10] = { 1,2,3,4,5,5,6,7,8,9 };
int arr2[10] = { 1,2,3,4,5,6,7,8,9,10 };
int ret = my_memcmp(arr1, arr2, 40);
if (ret > 0)
{
printf("arr1数组里的数大于arr2数组里的数\n");
}
else
if (ret == 0)
{
printf("arr1数组里的数等于arr2数组里的数\n");
}
else
{
printf("arr1数组里的数小于arr2数组里的数\n");
}
return 0;
}
· 4个内存函数的介绍与模拟就结束了,就我个人总结来讲,内存操作函数都是进行一个字节一个字节的访问,只要掌握了字节访问的方法问题就不大了~
· 欢迎各位uu的指正和建议~