C language memory function introduction and implementation

Table of contents

foreword

One: memory copy function

(1) memcpy ( ) function

(2) memove ( ) function

Two: memory comparison function

Three: memory setting function


foreword

The function declarations of the functions introduced in this article are all in the header file string.h.

One: memory copy function

(1) memcpy ( ) function

Function declaration: void* memcpy(void* dest, const void* src, size_t num)

Function: Copy the bytes of one piece of memory space to another piece of memory space.

The meaning of function parameters:

① dest points to the target array used to store the copied content, and the type is cast to a void* pointer.

②src points to the data source to be copied, and the type is cast to a void* pointer. At the same time, we just copy the data in this space to the target space instead of modifying it, so we use const to modify it.

③num (unsigned integer) indicates the number of bytes to be copied.

Function return value:

After the function call ends, in order to facilitate us to judge whether the copy is successful, we return the target address.

transfer:

baf1c0b67d0f4a0f9dc9ba1ef0414a43.png

 Ideas for simulation implementation:

To exchange bytes one by one, we can forcibly convert the passed pointer to char* type and dereference it to get

One byte is exchanged, and then the iteration continues, controlling the loop through the num passed in.

Notice:

①*(char*)dest++ is not allowed, because the priority of ++ is higher than that of forced type conversion, and ++ is illegal for empty type.

②*((char*)dest)++ is possible in C, but not in C++, because the temporary variables generated by forced conversion cannot be ++ operated in C++.

code:

//内存拷贝函数(拷贝不重叠)加测试
void* my_memcpy(void* dest, const void* src, size_t num)
{
	//断言,不能传空指针进来
	assert(dest && src);
	//记录目标地址
	void* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		//对空类型计算是不符合规则的
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}
int main()
{
	int arr1[20] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[5] = { 0 };
	//int类型占4个字节
	//交换20个字节就是交换数组前5个元素
	my_memcpy(arr2, arr1, 20);
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

(2) memove ( ) function

Function declaration: void* memove(void* dest, const void* src, size_t num)

Function: used to copy two overlapping memory spaces.

The meaning of function parameters:

① dest points to the target array used to store the copied content, and the type is cast to a void* pointer.

②src points to the data source to be copied, and the type is cast to a void* pointer. At the same time, we just copy the data in this space to the target space instead of modifying it, so we use const to modify it.

③num (unsigned integer) indicates the number of bytes to be copied.

Function return value:

After the function call ends, in order to facilitate us to judge whether the copy is successful, we return the target address.

transfer:

133c1699ed2d4f36a954c449a04c9dca.png

Why separate out the overlapping cases? Let's look at the following situation:

323d8d67ba654969a2976fed54675d91.png

 In the case where the target address is greater than the source address, if the data to be copied is only 2 and 3, there is no problem.

But if we want to copy 2, 3, 4, 5, we want 1, 2, 3, 2, 3, 4, 5, 8. But in fact, we have already overwritten 4 when we made the first copy.

To prevent the following data from being overwritten in advance, we can copy from the back to the front, that is, first assign 5 to 7, and then assign 4 to 6, which solves the problem of the value being overwritten.

Ideas for simulation implementation:

① Classify, if the target address is less than the source address, copy forward and backward; if the target address is greater than or equal to the source address, copy forward and backward.

② Exchange bytes one by one, we can forcibly convert the passed pointer to char* type and dereference it, and get

One byte is exchanged, and then the iteration continues, controlling the loop through the num passed in.

 

code:

//内存拷贝函数(重叠)和测试
void* my_memmove(void* dest, const void* src, size_t num)
{
	//	断言,不能传空指针进来
	assert(dest && src);
	void* ret = dest;
	//如果目标地址小于源地址,前向后拷贝
	if (dest < src)
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			//对空类型计算是不符合规则的
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	//如果目标地址大于或者等于源地址,后向前拷贝
	else
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}

int main()
{
	int arr1[10] = { 0,1,2,3,4,5,6,7,8,9 };
	//把0,1,2拷贝到3,4,5
	my_memmove(arr1+4, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

Two: memory comparison function

memcmp( ) function

Function declaration: int memcmp(const void* ptr1, const void* ptr2, size_t num)

Function: It is used to compare two pieces of memory space. The comparison here is not to compare data, but to compare bytes one by one. When different bytes are encountered, the size is judged.

The meaning of function parameters:

①ptr1 and ptr2 point to the target array to be compared, and the type is cast to a void* pointer. At the same time, we are only comparing rather than modifying, so we use const for modification.

②num (unsigned integer) indicates the number of bytes to be compared.

Function return value:

If every byte in the two spaces is the same, it will return 0, if the previous one is large, it will return a number greater than 0, and if the previous one is small, it will return a number smaller than 0.

transfer:

a216d1c615094d72a00f503f153872e6.png

Ideas for simulation implementation:

① Compare bytes one by one, and use num to control the number of cycles.

②If they are not the same, directly return the difference between the two bytes.

③If the loop ends, it means that the first num bytes are the same, and return 0.

code:

//内存比较函数和测试
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	//断言,不能传空指针进来
	assert(ptr1 && ptr2);
	while (num--)
	{
		if (*(char*)ptr1 != *(char*)ptr2)
			return *(char*)ptr1-*(char*)ptr2;
		//如果相等,迭代
		ptr1 = (char*)ptr1 + 1;
		ptr2 = (char*)ptr2 + 1;
	}
	return 0;
}

int main()
{
	int arr1[10] = { 0,1,2,3,4,5,6,7,8,1 };
	int arr2[20] = { 0,1,2,3,4,5,6,7,8,10 };
	int ret = my_memcmp(arr1, arr2, 40);
	printf("%d ", ret);
	return 0;
}

Three: memory setting function

memset( ) function

Function declaration: void* memset(void* ptr, int value, size_t num)

Function: Used to initialize the memory space (in bytes).

The meaning of function parameters:

①ptr points to the target array to be initialized, and the type is cast to a void* pointer.

②value indicates the value to be set. The value is passed as an int, but the function uses the unsigned char form of the value when filling the memory block.

Let’s focus on the value parameter. You must know that we initialize each byte. One byte cannot store data as large as 1000. In this case, the last byte of 1000 is used for initialization.

For example, the results of passing in 1000 and 232 initialization are the same.

③num (unsigned integer) indicates the number of bytes to be initialized.

Function return value:

After the function call ends, in order to facilitate us to judge whether the initialization is successful, we return the target address.

transfer:

bf2aa9a5bffd4ad4b8702a8d4aac102f.png

 718260aa09624902ab4e2ba356792d2d.png

Ideas for simulation implementation:

To initialize each byte, we can forcibly convert the passed pointer to char* type and dereference it to get

A byte is initialized, and then continues to iterate, and the loop is controlled by the num passed in.

code:

//内存设置函数(初始化)
void* my_memset(void* ptr, int value, size_t num)
{
	//断言,不能传空指针进来
	assert(ptr);
	void* ret = ptr;
	while (num--)
	{
		*(char*)ptr = value;
		(char*)ptr = (char*)ptr + 1;
	}
	return ret;
}

int main()
{
	int arr[10] = { 0 };
	//只认最后一个字节(输入1000和232结果是一样的)
	my_memset(arr, 232, 40);
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 

Guess you like

Origin blog.csdn.net/2301_76269963/article/details/130092993