当前位置:网站首页>C语言-内存操作函数

C语言-内存操作函数

2022-08-11 05:30:00 CHAKMING1

目录

一、内存函数详解

1.memcpy函数

2.memmove函数

3.memcmp函数

4.memset函数


一、内存函数详解

1.memcpy函数

为什么会有memcpy函数呢,这个函数与strcpy有什么区别,首先strcpy是字符串操作函数,那么我们如果想对整型、浮点型以及我们自己自定义的数据类型要如何操作,这时候就可以使用memcpy函数。

void * memcpy ( void * destination, const void * source, size_t num );

上面是函数的格式,void*类型是可以返回任意类型的指针。

destination:是接受要复制的内容的一个指针,同样是void*类型的

source:是要复制过去的来源指针,这里加上const是因为防止source被修改

num:复制的字节数,size_t是一个无符号类型

这个函数本质上是可以接受任何的指针类型,所以使用了void*来当作一个“万能”的作用,再通过类型转换,而转换成实际我们想要的指针类型。

void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src); // 进行断言,需要包含头文件assert.h
	void* ret = dest; // 定义一个ret接受dest,防止dest直接被修改无法返回
	while (num--)
	{
		// 实际我们在传输过程中,无论是任何的数据类型,我们都是一个字节一个字节传
        // 因为需要转换成char*类型,这样每次指针移动都是移动一位
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}	
	return ret;
}

以上就是memcpy函数的内部实现,那么下面这段代码是否有问题?

int main() 
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memcpy(arr + 2, arr, sizeof(int)*5);
	for (int i = 0; i < 10; i++) {
		printf("%d ", arr[i]);
	}
	printf("\n");
}

我们预想的结果可能是1,2,1,2,3,4,5,8,9,10,但实际并不是这样的。

实际输出的效果是这样,因为这个函数是没办法对有重复的内存区域进行复制的,因为我们在复制过程中,到第三位的时候,这个值以及被改掉了,所以之后的数一直复制的都是1,2,这就导致了这个值不是我们想要的。但实际,用库函数中的memcpy不会发生这种情况,因为编译器已经预料到我们会这样操作,所以现在有些编译器中memcpy函数也可以对这种情况进行操作,但是不建议这么做。

所以为了解决重叠拷贝的问题就有了memmove这个函数

2.memmove函数

memmove函数是在memcpy函数的基础上,可以对有重复包含的内存区域进行复制,得到我们想要的结果。

void * memmove ( void * destination, const void * source, size_t num );

这是memmove函数的格式,与memcpy函数一致,这里不做详细解释。

那么,这个函数是如何实现的?

void *my_memmove(void *dest, const void *src, size_t count)
{
    assert(dest && src);

    void *ret = dest;
    // dest 为低地址,就从前向后拷贝
    if (dest < src)
    {
        while (count)
        {
            *(char *)dest = *(char *)src;
            dest = (char *)dest + 1;
            src = (char *)src + 1;
            count--;
        }
    }
    // dest 为高地址,就从后向前拷贝
    else
    {
        while (count--)
        {
            *((char *)dest + count) = *((char *)src + count);
        }
    }
    return ret;
}

 本质上,这个函数其实内部进行复制的过程与memcpy函数一致,但有一个不同的地方在于,如果说目标地址要比源头地址高,我们就从后向前进行拷贝,如果是目标地址比源头地址低,则还是按照memcpy函数的拷贝方式。

这样,我们就能得到想要的结果。

3.memcmp函数

这个函数是一个内存比较函数,比较两个指针开始的num字节大小,返回值与strcmp一致。

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

比较ptr1和ptr2指针开始的num个字节,返回值是int类型,返回值如下:

 从第一个字节开始比较,如果ptr1大于ptr2,则直接返回一个大于0的数,ptr1等于ptr2,则继续往后比较,这时候num--,直到num等于0,两个指针还是相等,则返回一个0,ptr1小于ptr2,则直接返回一个小于0的数字。

int my_memcmp(const void* ptr1, const void* ptr2, size_t count)
{
	assert(ptr1 && ptr2);
    // 因为在while循环就进行了比较,所以要先--
	while (--count && *(char*)ptr1 == *(char*)ptr2) // 这里是遇到不同后,退出
	{
		((char*)ptr1)++;
		((char*)ptr2)++;
	}
	return *(char*)ptr1 - *(char*)ptr2; // 直接返回两个指针对应的值的差值
}

4.memset函数

void * memset ( void * ptr, int value, size_t num );

这是一个内存设置函数,ptr是需要被设置的指针,value是设置的值,num是从开始地址的num个字节,设置为value值。

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

int main ()
{
  char str[] = "almost every programmer should know memset!";
  memset (str,'-',6);
  puts (str);
  return 0;
}

 输出结果:------ every programmer should know memset

原网站

版权声明
本文为[CHAKMING1]所创,转载请带上原文链接,感谢
https://blog.csdn.net/CHAKMING1/article/details/124163610