Teach you how to play with memory functions (including simulation implementation)

Table of contents

1. memcpy

1. Know memcpy

2. Use memcpy

3. Expansion: Simulate the implementation of memcpy

Two, memmove

1. Know memmove

2. Use memmove

3. Expansion: Simulate memmove

3. memcmp

1. Know memcmp

2. Use memcmp

Four, memset

1. Know memset

2. Use memset

3. Expansion: Simulate the implementation of memset


1. memcpy

1. Know memcpy

The following pictures about function definitions are from: cplusplus.com - The C++ Resources Network 

The function of the memcpy function is to copy n bytes from the starting position of the memory address pointed to by the source src to the starting position of the memory address pointed to by the target dest. The return type of memcpy is void*, and the parameter type is void* , one is const void*, and the other is unsigned integer, that is, size_t. The    reason why one is modified with const and the other is not modified with const is because the target we want to modify is only the content pointed to by dest, and will not be modified to src the content pointed to. One thing to pay attention to is: this function operates on bytes, it does not grant permissions based on the type you pass to it, it modifies byte by byte.

2. Use memcpy

#include<stdio.h>
#include<string.h>//memcpy位于这个头文件中
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 4,3,1,2,6,8,7,11,10,9 };
	memcpy(arr1, arr2, 20);
   //将arr1所指向地址的20个字节一个一个转换为arr2所指向地址的20个字节
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}//将修改之后的数组打印出来
}

 

 

3. Expansion: Simulate the implementation of memcpy

First of all, we need to clarify the goal of our function . Its goal is to convert the 20 bytes of the address pointed to by dest to the 20 bytes of the address pointed to by src.    Then our parameter must have two addresses, so In order to access the content pointed to by dest and src and access byte by byte through the address, but we don’t know what data type the user will pass to us, so the type of our two data must first be void* , and because we only modify the content pointed to by dest, the content pointed to by src will not be modified, so the type of the src parameter must be const void* and then we should also know how many bytes to copy, So we also need an integer parameter.

The basic framework is known, and the next step is to implement

We know the address of the two data, one is the data used to copy the data, the other is the copy content, the data used to copy the data has to be converted into the copy content, and because it is a byte-by-byte copy, so in Before copying, we have to convert both data types to char* because the operation authority of char* is 1 byte, that is, +1 will only skip one byte, so that one byte can be realized Copy the data one byte at a time.

The idea is also there, the code will come out naturally

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* strc, size_t num)
{
	assert(dest && strc);//断言,避免使用者传递空指针
	int i = 0;
	for (i = 0; i < num; i++)//通过循环的方式一个字节一个字节的跳动
	{
		*((char*)dest + i) = *((char*)strc + i);//将对应的字节拷贝到目标数据上
	}
	return dest;//返回地址
}
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 4,3,1,2,6,8,7,11,10,9 };
	int a = 0;
	scanf("%d", &a);
	my_memcpy(arr1, arr1 + 2, a);
	//memcpy(arr1, arr2, 20);
	for (int i = 0; i < 10; i++)//通过循环将拷贝后的结果打印出来
	{
		printf("%d ", arr1[i]);
	}
}

Two, memmove

1. Know memmove

The function of memmove is actually the same as that of memcpy, the only difference is that memmove can also copy when the address overlaps, and memcpy may cause problems when copying when the content overlaps. Of course, different compilers implement   memcpy differently. Similarly, some compilers implement memcpy exactly the same as memmove. Later we will show the problems that occur when memcpy written according to our method when copying overlapping content. It can be said that memmove that memcpy can do can also do. The return type of memmove is void*, two of the three parameters are addresses of void type, one of which points to an unchangeable content (decorated by const), and one is an unsigned integer.

2. Use memmove

#include<stdio.h>
#include<string.h>
#include<assert.h>
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    memmove(arr1 + 4, arr1 + 2, 20);
   //将该数组的3,4,5,6,7拷贝在该数组的5,6,7,8,9
	for (int i = 0; i < 10; i++)//通过循环将拷贝完成后的数据打印出来
	{
		printf("%d ",*(arr1+i));
	}
}

 Then why did we say that our memcpy made an error when copying the content of overlapping addresses, here I draw the picture below to explain to you, assuming we have such an integer array

 Then when we want to copy 4, 5, 6, 7 here to 2, 3, 4, 5, it should be written like this according to the previous code

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* str1, const void* str2, int num)
{
	assert(str1 && str2);
	int i = 0;
	for (i = 0; i < num; i++)
	{
		*((char*)str1+i) = *((char*)str2+i);
	}
	return str1;
}
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memcpy(arr1+3, arr1+1, 16);
   //arr1+3的地址所指向的为该数组中的4,arr1+1所指向的为该数组中的2
   //16个字节为4个整型的长度
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
}

Then according to the memcpy we wrote before, it is to copy 4 into 2 through a byte-by-byte change, and then copy 5 into 3. Then stop, we see the second picture

 At this moment, the array should look like this

 Then you will find a problem at this moment, our goal is to copy 4, 5, 6, 7 into 2, 3, 4, 5 and that's it

But if we continue to copy, that is to copy the last two 2, 3 on 2, 3, 2, 3 to 6, 7 and it will be like this 

3. Expansion: Simulate memmove

The core problem has been stated, and the solution is mentioned next. It is very simple. It is not difficult to see that the problem is actually in the overlapping part. Here I will directly state the conclusion. We have to copy the overlapping part to the target first . Then it is reasonable to copy the other parts to the target to    continue with our previous example

 Just imagine, when copying, we first copy 5 to 6, then copy 4 to 7, then copy 2 to 4, and finally copy 3 to 5, that is, copy from back to front , will there still be the previous problem? Obviously not, another overlapping situation, just copy from the front to the back, and it doesn't matter when there is no overlap. To sum up, when dest<src, copy from the front to the back, and when dest>src, copy from the back to the front, which is our situation. You have to draw the picture below to understand it perfectly

upper code

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* dest,const void* src,int num)
{
	int i = 0;
	assert(dest && src);
	if (dest < src||dest==src)
	{
		for (i = 0; i < num; i++)
		{
			*((char*)dest + i) = *((char*)src + i);
		}
	}
	else if (dest > src)
	{
		while(num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return dest;
}
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr1+4, arr1+2, 20);
    //memmove(arr1 + 4, arr1 + 2, 20);
	//1 2 3 4 3 4 5 6 7 10
	for (int i = 0; i < 10; i++)
	{
		printf("%d ",*(arr1+i));
	}
}

3. memcmp

1. Know memcmp

The role of memcmp is to compare the size of two data at the memory storage level, and num is the number of bytes they compare. For    example, if I want to compare two integer data, I need to pass two integer addresses. At the same time, an integer variable (or unsigned integer) with a size of 4 must be passed, so that it is possible to know which integer is larger through a byte-by-byte comparison. When the content of the address pointed to by ptr1 is less than the content pointed to by ptr2, return a number less than 0, greater than return a number greater than 0, equal to return 0, which is close to the previous strcmp The return type of the memcmp function is an integer, and the parameters are two     empty Type pointer and an unsigned integer, the content pointed to by the address of these two empty type pointers cannot be modified (const). The reason for this design is that we only compare the size and do not need to change the value of the corresponding content.

2. Use memcmp

#include<stdio.h>
#include<string.h>//memcmp位于这个头文件中
int main()
{
	int a = 3;
	int b = 4;
	printf("%d",memcmp(&a, &b, 4));//将比较结果打印出来
}

 Here I will not simulate it, the main reason is that I will not. In the process of trying to simulate, I thought about converting the data into a char* type and comparing it byte by byte, which sounds reasonable. Yes, but it has a fatal problem, that is, the weight problem. For example, the two numbers 7 and 11, if their type is an integer, then their storage is stored in binary form, in 32-bit Their storage on the machine is

00000000000000000000000000000111//7
00000000000000000000000000001011//11

But it is impossible for us to judge the size of these two data as soon as we encounter a different one. If we judge as soon as we encounter a different one, then i will have a funny situation where 7 is greater than 11. The author really doesn’t know how to do this. If you know how this function is implemented, you can post the corresponding link in the comment area, thank you very much!

Four, memset

1. Know memset

The role of memset() is to fill a given value in a block of memory. Its return type is a void pointer, three parameter types, one is an address, one is an integer, and one is an unsigned integer. Memset The function is to replace num bytes of data with value

2. Use memset

#include<stdio.h>
#include<string.h>//memset位于这个头文件中
int main()
{
	char arr1[] = "abc_def";
	memset(arr1,'x', 2);
//将arr1所给地址的内容,一个字节一个字节的修改成'x',共修改两个字节
	printf("%s", arr1);
}

 

 

3. Expansion: Simulate the implementation of memset

#include<stdio.h>
#include<string.h>
void* my_memset(void*dest,int src,size_t num)
{
	int i = 0;
	for (i = 0;i<num; i++)
	{
		*((char*)dest + i) = (char)src;
    //通过强制类型转换和解引用,一个字节一个字节的实现目的
	}
	return dest;
}
int main()
{
	char arr1[] = "abc_def";
	//memset(arr1,'x', 3);
	my_memset(arr1, 'x',3);
	printf("%s", arr1);
}

Well, today’s sharing is over here, thank you friends for visiting, I wish you all a bright future

Guess you like

Origin blog.csdn.net/fq157856469/article/details/131659082