探索内存函数的奥秘【memcpy、memmove、memset、memcmp】

目录

一,memcpy函数

1,memcpy函数简介

2,memcpy函数的原理

3,memcpy函数的用法

4,注意事项

5,memcpy函数模拟实现

二,memmove函数

1,memmove函数简介

2,memmove函数的原理

3,memmove函数的用法

4,注意事项

5,memmove函数模拟实现

三,memset函数

1,memset函数简介

2, memset函数的原理

3,memset函数的用法

4,注意事项

四,memcmp函数

1,memcmp函数简介

2,memcmp函数功能

3,memcmp函数的用法 


一,memcpy函数

1,memcpy函数简介

memcpy函数的作用是将源内存块的内容复制到目标内存块中。

函数头文件: 

#include 

 函数原型:

void * memcpy ( void * destination, const void * source, size_t num );
  • dest:目标内存块的起始地址。
  • src:源内存块的起始地址。
  • num:要拷贝的字节数。
  • 该函数返回指向目标内存块的指针。

2,memcpy函数的原理

  • 它通常采用字节拷贝的方式来实现内存块的复制
  • 具体来说,memcpy函数会从源内存块中逐个字节地读取数据,并将其逐个字节地写入目标内存块中,直到拷贝完成为止。
  • 由于这种逐字节的拷贝方式,memcpy函数在处理大内存块时可能会比较耗时,因此在一些情况下可能会有更高效的替代方案。

3,memcpy函数的用法

将arr1数组里边的数(在内存中占20个字节)拷贝到arr数组里边去。

#include 
#include 

int main()
{
	int arr[10] = { 0 };
	int arr1[] = { 1,2,3,4,5 };

	memcpy(arr, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

 运行结果:

4,注意事项

  1. 内存重叠: 源内存块和目标内存块通常不应该重叠,否则会导致未定义的行为。

  2. 边界检查:需要确保拷贝的字节数不超过源内存块和目标内存块的实际大小,以免发生越界访问。

  3. 指针类型:需要注意指针类型的转换,确保传递给memcpy函数的参数类型正确。

5,memcpy函数模拟实现

#include 
#include 
#include 

void* my_memcpy(void* dest, void* src, size_t sz)
{
    void* ret = dest;
	assert(dest && src);
	while (sz--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
    return ret;
}

int main()
{
	int arr[10] = { 0 };
	int arr1[] = { 1,2,3,4,5 };
	my_memcpy(arr, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

二,memmove函数

1,memmove函数简介

memmove函数的作用是将源内存块的内容移动到目标内存块中。与memcpy函数不同的是,memmove函数能够处理源内存块和目标内存块重叠的情况。

 函数头文件:

#include 

 函数原型:

void * memmove ( void * destination, const void * source, size_t num );
  • dest:目标内存块的起始地址。
  • src:源内存块的起始地址。
  • num:要移动的字节数。
  • 该函数返回指向目标内存块的指针。

2,memmove函数的原理

  • memmove 函数的实现原理会比memcpy稍微复杂一些,因为它需要处理源内存块和目标内存块重叠的情况。
  • 通常,memmove函数会采用一种类似于缓冲区的机制,先将源内存块的内容复制到一个临时缓冲区中,然后缓冲区的内容复制到目标内存块中,从而避免了重叠拷贝导致的数据错乱。
  • 这种机制使得memmove函数在处理重叠内存块时能够保证正确的移动操作。

3,memmove函数的用法

#include 
#include 

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

	memmove(arr, arr + 2, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;

  运行结果:

4,注意事项

  1. 内存重叠: 虽然memmove函数能够处理重叠的内存块,但仍需谨慎处理,以免出现意外的情况。

  2. 边界检查:确保拷贝的字节数不超过源内存块和目标内存块的实际大小,以免发生越界访问。

  3. 指针类型:需要注意指针类型的转换,确保传递给memmove函数的参数类型正确。

5,memmove函数模拟实现

#include 
#include 
#include 

void* my_memmove(void* dest, const void* src, size_t sz)
{
	void* ret = dest;
	assert(dest && src);

	if (dest < src)
	{
		//前->后
		while (sz--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//后->前
		while (sz--)
		{
			*((char*)dest + sz) = *((char*)src + sz);
		}
	}
	return ret;
}

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

	memmove(arr, arr + 2, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

三,memset函数

1,memset函数简介

memset函数的作用是将指定内存块的内容设置为指定的值。

 函数头文件:

#include 

  函数原型:

void * memset ( void * ptr, int value, size_t num );
  •  ptr:指向要设置数值的内存块的指针
  • value:要设置的值
  • num:要设置的字节数
  • 该函数返回值指向内存块的指针

2, memset函数的原理

  •  通常使用一个循环来逐个字节地设置内存块的内容为指定的值
  • 由于内存的底层表示是字节,因此逐字节设置是一种通用且高效的方法
  • 在某些特定的平台上,memset函数可能会进行一些优化,以提高性能

3,memset函数的用法

示例1:初始化数组:

#include 
#include 

int main()
{
	int arr[5];
	
	//将数组所有的元素初始化为0
	memset(arr, 0, sizeof(arr));
	for (int i = 0; i < 5; i++)
	{
		printf("%d", arr[i]);
	}

	return 0;
}

   运行结果:


示例2:清空字符串: 

#include 
#include 

int main()
{
	char str[] = "hello world";

    //将字符串str的所有字符设置为0
	memset(str, 0, sizeof(str));

    //输出空字符串
	printf("%s\n", str);

	return 0;
}

    运行结果:

调试时内存中情况: 

探索内存函数的奥秘【memcpy、memmove、memset、memcmp】_第1张图片


示例3:内存分配和释放: 

#include 
#include 
#include 

int main()
{
	char* str = (char*)malloc(10 * sizeof(char));

	//对动态分配的内存进行初始化
	memset(str, 0, 10 * sizeof(char));
	strcpy(str, "hello");
	printf("%s\n", str);//输出:hello
	free(str);//释放内存

	return 0;
}

     运行结果:

4,注意事项

  • 内存越界:确保设置的字节数不超过内存块的实际大小,以避免发生越界访问

  • 指针类型:需要注意指针类型的转换,确保传递给memset函数的参数类型正确

  • 对结构体和类的使用:在对结构体和类的内存块进行初始化时,需要谨慎处理,以避免出现意外的情况 

四,memcmp函数

1,memcmp函数简介

memcmp函数可以比较两个内存块的内容是否相等,并返回比较结果,通常用于比较字符串、数组或者其它内存块的内容。

  函数头文件:

#include 

  函数原型:

int memcmp ( const void * ptr1, const void * ptr2, size_t num );
  • ptr1:要比较的第一个内存块的起始地址。
  • ptr2:要比较的第二个内存块的起始地址。
  • num:要比较的字节数。

2,memcmp函数功能

  • 按字节逐个比较两个内存块中的内容,直到比较了num个字节或者遇到不相等的字节为止。

  • 如果两个内存块的内容完全相等,则返回0。

  • 如果第一个内存块小于第二个内存块,则返回一个负数。

  • 如果第一个内存块大于第二个内存块,则返回一个正数。 

3,memcmp函数的用法 

示例1:比较字符串:

#include 
#include 

int main()
{
	char str1[] = "hello";
	char str2[] = "world";
	if (memcmp(str1, str2, 5) == 0)
	{
		printf("两个字符串相等\n");
	}
	else
	{
		printf("两个字符串不相等\n");
	}

	return 0;
}

   运行结果:


示例2:比较数组:

#include 
#include 

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3,4,6 };
	if (memcmp(arr1, arr2, 5 * sizeof(int) == 0))
	{
		printf("两个数组相等\n");
	}
	else
	{
		printf("两个数组不相等\n");
	}

	return 0;
}

   运行结果:

你可能感兴趣的:(C语言从入门到精通,c语言,memcmp,memset,memmove,memcpy)