C语言常用内存函数(超详细版)

发布于:2023-01-04 ⋅ 阅读:(221) ⋅ 点赞:(0)

目录

memcpy函数

使用实例

模拟实现

memmove函数

使用实例

模拟实现

memcmp函数

 使用实例

模拟实现

memset函数

使用实例



字符(串)函数可以专门对字符或字符串操作,同时,若要对其他类型数据进行这些操作,就可以借助内存函数直接对内存操作,接下来介绍的几个内存函数就是极其常用的。


memcpy函数

  • void* memcpy( void* destination , const void* source, size_t num);
  • 从source的位置开始拷贝numge个字节的数据到destination的内存位置;
  • 所有类型的数据都可以拷贝,所以返回值是void* 类型;
  • 遇到 ' \0 ' 的时候不会停下来;
  • 对自己内容的一部分拷贝给自己是无效的;

使用实例:

#include<stdio.h>
#include<string.h>

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

	memcpy(destination, source, 5 * sizeof(int));

	return 0;
}

 

模拟实现:

关键思路:

既然返回类型和形参类型都是void* ,那对于不同的类型数据怎么保证全部拷贝呢?

可以强转为char*型,这样就可以不放过每个字节对应的数据了;

#include<stdio.h>
#include<string.h>
#include<assert.h>

void* my_memcpy(void* destination, const void* source, size_t num)
{
	assert(destination && source);
	void* start = destination;
	while (num--)
	{
		*((char*)destination)++ = *((char*)source)++;
	}
	//warning C4716 : “my_memcpy”: 必须返回一个值
	return start;
}
int main()
{
	int source[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int destination[5] = { 0 };

	my_memcpy(destination, source, 5 * sizeof(int));

	for (int i = 0; i < 5; i++)
	{
		printf("%d ", destination[i]);
	}

	return 0;
}

 注意点:

 


memmove函数

  • void * memmove ( void * destination, const void * source, size_t num );
  • memcpy 的差别就是 memmove 函数处理的源内存块和目标内存块是可以重叠的;
  • 如果源空间和目标空间出现重叠,就得使用 memmove 函数处理。

使用实例:

 对于上述第二点:

模拟实现:

关于该函数的模拟实现也就有的研究了。

比如:对于数组arr自身要实现移动:必须考虑数据覆盖问题

如果要移动的数据的起始位置在目标位置之前:就应该依次先移动最后面的数据(从后往前);

如果要移动的数据的起始位置在目标位置之后:就应该依次先移动前面的数据(从前往后);

 

 秘诀:其实就是从它们相交的位置开始移动

#include<stdio.h>
#include<string.h>
#include<assert.h>

void* my_memmove(void* destination, const void* source, size_t num)
{
	assert(destination && source);
    void* ret = destination;
    //前 -> 后
    //dest < src
    if (destination < source)
    {
        while (num--)
        {
            *(char*)destination = *(char*)source;
            destination = (char*)destination + 1;
            source = (char*)source + 1;
        }
    }
    //后 -> 前
    //dest > src
    else
    {
        while (num--)
        {
            *((char*)destination + num) = *((char*)source + num);
        }
    }

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

	my_memmove(source, source + 5, 5 * sizeof(int));

	return 0;
}


memcmp函数

  • int memcmp ( const void * ptr1, const void * ptr2, size_t num );
  • 比较ptr1和ptr2各自后面num个字节的数据是否相同;
  • 先遇到谁的小谁的就小;
  • 特点:可以作用于任何类型的数据;
  • 返回值:
  •  

 使用实例:

#include<stdio.h>
#include<string.h>

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

	int ret = memcmp(arr1, arr2, 5 * sizeof(int));

	printf("%d\n", ret);

	return 0;
}

模拟实现:

#include<stdio.h>
#include<string.h>
#include<assert.h>

int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	assert(ptr1 && ptr2);
	int ret = 0;
	while (num--)
	{
		ret = *((char*)ptr1) - *((char*)ptr2);
		ptr1 = (char*)ptr1 + 1;
		ptr2 = (char*)ptr2 + 1;
		if (ret != 0)
		{
			return ret;
		}
	}

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

	int ret = my_memcmp(arr1, arr2, 5 * sizeof(int));

	printf("%d\n", ret);

	return 0;
}


memset函数

  • Sets buffers to a specified character.
  • void *memset( void *dest, int value, size_t count );
  • Return Value :memset returns the value of dest.

使用实例: 

#include<stdio.h>
#include<string.h>

int main()
{
	char arr[20] = { "hello world" };
	memset(arr + 6, 'x', 6 * sizeof(char));

	return 0;
}

 

 注意:

memset函数的赋值是按照字节为单位的(见下图4),赋值1,实则是在内存中全部放了0x010101010101....... 这个数刚好是10进制的16843009

因此:该函数不能对整形数组赋除 0 和 -1 之外的数;

 

 

 

 

本文含有隐藏内容,请 开通VIP 后查看