C语言 内存函数

C语言 内存函数

  • 一、内存复制函数
    • 1.1 memcpy函数
    • 1.2 memmove函数
  • 二、内存比较函数 memcmp
  • 三、内存查找字符函数 memchr
  • 四、内存设置函数 memset

前言:C语言提供了许多与内存相关函数,可以在头文件中查看函数声明,本章将会自行编写相关内存函数

一、内存复制函数

1.1 memcpy函数

功能:
将num字节的值从source指向的位置直接拷贝到destination指向的内存块,该函数不检查源中是否有’\0’字符——它总是精确地复制num字节。但是source与destination发生内存重叠,结果是未定义的

库函数memcpy声明
void * memcpy ( void * destination, const void * source, size_t num );
返回值:返回目标起始位置
destination :目标指向内存块起始地址
source:源指向内存块起始地址
num :需要复制的字节数

模拟实现

void* my_memcpy(void* destination, const void* source, size_t num)
{
	assert(destination && source);//检查destination与source是否为空指针
	char * des = (char *)destination; //将void * 类型转换为char *类型,便于后面指针算术运算
	const char * src = (char*)source;
	while (num--)
	{
		*des++ = *src++;
	}
	return destination;
}

警告:
如果源与目标以任何形式发生内存重叠,它的结果是未定义的。当发生内存重叠应该使用memmove函数而不是memcpy函数

例:
int arr[10] = {1,2,3,4,5,6,7,8,9,10}
将数组下标0-3对应元素值依次复制到下标2-5对应元素
预想复制后数组为int arr[10] = {1,2,1,2,3,4,7,8,9,10},但实际数组为int arr[10] = {1,2,1,2,1,2,7,8,9,10}
因为从下标第2-3元素发生内存重叠。复制后下标2元素为1,下标3元素为2,所以下标为4元素值变为1,下标为5元素值变为2

C语言 内存函数_第1张图片

#include 
#include 
void* my_memcpy(void* destination, const void* source, size_t num)
{
	assert(destination && source);//检查destination与source是否为空指针
	char * des = (char *)destination; //将void * 类型转换为char *类型,便于后面指针算术运算
	const char * src = (char*)source;
	while (num--)
	{
		*des++ = *src++;
	}
	return destination;
}


int main()
{

	int arr[] = { 1,2,3,4,5,6,7,8,9,10};
	my_memcpy(arr + 2, arr, 16);//destination为arr[2]地址,source为arr[0]地址,复制16,即4个int类型大小
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

输出

1 2 1 2 1 2 7 8 9 10

1.2 memmove函数

功能:
将num字节的值从source指向的位置直接拷贝到destination指向的内存块,该函数不检查源中是否有’\0’字符——它总是精确地复制num字节。source与destination可以发生内存重叠

库函数memmove声明
void * memmove ( void * destination, const void * source, size_t num );
返回值:返回目标起始位置
destination :目标指向内存块起始地址
source:源指向内存块起始地址
num :需要复制的字节数

memmove函数允许source与destination可以发生内存重叠。那么在复制时有三种处理方式
情况1: source地址 < destination地址 时将从后向前复制
情况2: source地址 > destination地址 时将从前向后复制
情况3: source地址 == destination地址时,从前向后或从后向前复制都可以,本案例会采用从前向后复制
C语言 内存函数_第2张图片

模拟实现

void * my_memmove(void * destination, const void * source, size_t num)
{
	assert(destination && source); //检查destination与source是否为空指针
	char * des = (char *)destination; //将void * 类型转换为char *类型,便于后面指针算术运算
	const char * src = (char *)source;
	if (src < des) //从后向前复制
	{
		while (num--)
		{
			*(des+num) = *(src+num);
		}
	}
	else //从前向后复制
	{
		while (num--)
		{
			*des++ = *src++;
		}
	}
	return destination;
}

测试

#include 
#include 

void * my_memmove(void * destination, const void * source, size_t num)
{
	assert(destination && source); //检查destination与source是否为空指针
	char * des = (char *)destination; //将void * 类型转换为char *类型,便于后面指针算术运算
	const char * src = (char *)source;
	if (src < des) //从后向前复制
	{
		while (num--)
		{
			*(des+num) = *(src+num);
		}
	}
	else //从前向后复制
	{
		while (num--)
		{
			*des++ = *src++;
		}
	}
	return destination;
}

int main()
{

	int arr1[] = { 1,2,3,4,5,6,7,8,9,10};
	int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr1 + 2, arr1, 16);//destination为arr[2]地址,source为arr[0]地址,复制16,即4个int类型大小
	int i = 0;
	printf("arr1:>\n");
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	printf("\n");
	my_memmove(arr2, arr2+2, 16);
	printf("arr2:>\n");
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
	return 0;
}

输出

arr1:>
1 2 1 2 3 4 7 8 9 10
arr2:>
3 4 5 6 5 6 7 8 9 10

二、内存比较函数 memcmp

功能:
memcmp对两段内存中的内容进行比较,两段内存分别起始ptr1和ptr2,共比较num个字节。当num个字节内容相等返回0,ptr1大于ptr2返回大于0值,ptr1小于ptr2返回小于0的值

库函数memcmp声明
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
ptr1 : 第一段内存起始地址
ptr2: 第二段内存起始地址
num: 比较字节个数

模拟实现

int my_memcmp(const void * ptr1, const void * ptr2, size_t num)
{
	assert(ptr1 && ptr2); //检查ptr1与ptr2是否为空指针
	const char * p1 = (char *)ptr1; //将void * 类型转换为char *类型
	const char * p2 = (char *)ptr2; //将void * 类型转换为char *类型
	while (num--)
	{
		if (*p1 == *p2)
		{
			p1++;
			p2++;
		}
		else
		{
			return *p1 - *p2;
		}
	}
	return 0;
}

三、内存查找字符函数 memchr

功能:
从ptr开始向后查找字符value第1次出现的位置,并返回一个指向该位置的指针,它最多向后搜寻num个字节。如果未找到,返回NULL指针

库函数memchr声明
const void * memchr ( const void * ptr, int value, size_t num );
ptr:待搜索内存起始位置
value :需要查找字符
num :要搜寻的字节个数

模拟实现

const void * my_memchr(const void * ptr, int value, size_t num)
{
	assert(ptr);
	const char * p = (char*)ptr;
	while (num--)
	{
		if (*p == value)
		{
			return (void*)p;
		}
		p++;
	}
	return NULL;

}

四、内存设置函数 memset

功能
把从ptr开始的num个字节都设置为字符值value

库函数memset声明
void * memset ( void * ptr, int value, size_t num );
ptr: 待设置内存起始位置
value :设置字符值
num :要设置字节的个数

模拟实现

void* my_memset(void* ptr, int value, size_t num)
{
	assert(ptr);
	char * p = ptr;
	while (num--)
	{
		*p++ = value;
	}
	return ptr;
}

你可能感兴趣的:(C语言,c语言,c++,数据结构)