[Happy Simulation] - Implémenter les fonctions memcpy et memmove avec la simulation C

teneur

1. Introduction à la fonction memcpy

1. Déclaration de fonction

2. Fonctions et précautions

3. Utilisation des fonctions

Deuxièmement, simulez l'implémentation de la fonction memcpy

1. Analyse de simulation

2. Mise en œuvre de la simulation

Troisièmement, l'introduction de la fonction memmove

1. Déclaration de fonction

2. Pourquoi y a-t-il une fonction memmove

3. Fonctions et précautions

4. Utilisation des fonctions

Quatrièmement, simulez l'implémentation de la fonction memmove

1. Analyse de simulation

 2. Mise en œuvre de la simulation

Résumer


1. Introduction à la fonction memcpy

1. Déclaration de fonction

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

2. Fonctions et précautions

  • La fonction memcpy copie num octets de données vers l'arrière depuis l'emplacement de la source vers l'emplacement mémoire de la destination.
  • Notez que cette fonction ne s'arrête pas lorsqu'elle rencontre '\0' .
  • S'il y a un chevauchement entre la source et la destination, le résultat de la copie est indéfini.
  • La fonction memcpy peut copier n'importe quel type de données, contrairement à la fonction strcpy qui ne peut copier que des chaînes.

3. Utilisation des fonctions

#include <stdio.h>
#include <string.h>//使用memcpy函数时记得引用它的头文件
int main()
{
	int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int arr2[5] = { 0 };//总共大小为20字节
	memcpy(arr1, arr2, 20//拷贝20个字节的数据);//将arr2中的数据拷贝到arr1中
	int i = 0;
	printf("拷贝后arr1中的数据为:");
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

résultat de l'opération :

Deuxièmement, simulez l'implémentation de la fonction memcpy

1. Analyse de simulation

1. Parce que nous ne savons pas quel type de données nous voulons copier, il peut s'agir de données de type char, de données de type int ou de données de type double. Les tailles de ces différents types de données sont différentes. Afin d'implémenter une fonction memcpy qui peut copier tous les types de données, nous ne pouvons copier que octet par octet, car la taille du plus petit type est d'un octet, de sorte que tous les types de données peuvent être copiés.

2. Comme nous ne savons pas quel type d'adresse est transmis à la fonction memcpy, nous utilisons un pointeur de type void* pour recevoir l'adresse transmise.

3. Étant donné que nous n'avons besoin que de copier les données stockées à l'adresse source vers l'adresse cible, nous n'avons qu'à modifier le contenu stocké à l'adresse cible, et non l'adresse stockée à l'adresse source. Nous devons donc utiliser un pointeur de type const void* pour recevoir l'adresse source.

4. Afin d'obtenir un accès chaîné, nous devons renvoyer l'adresse de départ de destination (destination) transmise. Puisque cette fonction changera le contenu du stockage de destination lors de son exécution, nous devons recréer un pointeur de type void* pour stocker cette adresse.

5. Afin d'éviter que l'adresse entrante ne soit un pointeur nul, nous devons utiliser assert pour affirmer que l'adresse entrante n'est pas un pointeur nul.

2. Mise en œuvre de la simulation

#include<stdio.h>
#include<assert.h>
//模拟实现memcpy
void* my_memcpy(void* dest, const void* scr, size_t count)
{
	assert(dest && scr);//断言传进来的地址不是空指针
	void* ret = dest;//保存目标起始地址
	while (count--)//拷贝源地址存储的数据
	{
		*(char*)dest = *(char*)scr;
		(char*)dest = (char*)dest + 1;
		(char*)scr = (char*)scr + 1;
	}
	return ret;//返回目标起始地址
}




//应用模拟实现的函数
int main()
{
	int arr1[] = { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 };
	int arr2[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	my_memcpy(arr2, arr1, 24);//拷贝6个字节的数据
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

résultat de l'opération :

Troisièmement, l'introduction de la fonction memmove

1. Déclaration de fonction

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

2. Pourquoi y a-t-il une fonction memmove

Pourquoi y a-t-il une fonction memmove ? Cela commence également par la fonction memcpy ci-dessus. Étant donné que la fonction memcpy ne peut pas copier les données d'un tableau sur elle-même (c'est-à-dire que les données cibles sont elles-mêmes, les données source sont également elles-mêmes, mais les données de différents emplacements dans un tableau sont copiées vers un autre emplacement), si vous copiez comme Des copies qui se chevauchent se produiront, entraînant des résultats qui ne sont pas ceux que nous attendions.

Comme ce code :

//应用模拟实现的memcpy函数
int main()
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	my_memcpy(arr + 2, arr, 24);//预期出现结果为1 2 1 2 3 4 5 6 9 10
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);//实际出现结果
	}
	return 0;
}

résultat de l'opération :

 Raisons pour lesquelles les résultats attendus et réels peuvent différer :

La raison de ce résultat est que des copies se chevauchent lorsque la fonction memcpy copie ses propres données à différents emplacements d'elle-même. L'adresse de départ des données source est arr et l'adresse de départ des données cibles est arr + 2. Lorsque nous entrons dans la fonction memcpy, nous copions d'abord les données à arr vers arr + 2 et copions les données à arr + 1 Les données sont copiées vers arr + 3. Lorsque nous voulons copier les données de arr + 2 vers arr + 4 , nous constatons que les données de arr + 2 ont été remplacées par les données de arr (1) , nous pouvons donc copier uniquement 1 vers arr + 4 ; lorsque nous voulons copier les données de arr + 3 vers arr + 5 , nous constatons que les données de arr + 3 ont déjà été remplacées par arr + 1 . data (2) , nous pouvons donc copiez seulement 2 à arr + 5 , en répétant comme ceciOverlapping copy , les données copiées sont toujours 1/2/1/2/1/2, jusqu'à ce que le nombre d'octets que nous voulons copier soit copié.

Ainsi, afin de copier nos propres données à différents emplacements, nous devons utiliser la fonction memmove pour l'implémenter.La fonction memmove a été créée pour résoudre le problème ci-dessus.

3. Fonctions et précautions

  • La différence entre memmove et memcpy est que le bloc mémoire source et le bloc mémoire cible traités par la fonction memmove peuvent se chevaucher.
  • Si l'espace source et l'espace cible se chevauchent, vous devez utiliser la fonction memmove pour y faire face.

4. Utilisation des fonctions

#include<stdio.h>
#include<string.h>//使用memmove函数时记得引用它的头文件
int main()                  
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	memmove(arr + 2, arr, 24);//预期出现结果为1 2 1 2 3 4 5 6 9 10
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);//实际出现结果
	}
	return 0;
}

 Cette fois, nous avons constaté que le résultat attendu copié avec la fonction memmove est le même que le résultat réel. Parlons de l'implémentation de la simulation de la fonction memmove.

Quatrièmement, simulez l'implémentation de la fonction memmove

1. Analyse de simulation

1. La méthode de transmission de l'adresse dans la fonction et la fonction recevant l'adresse est la même que la fonction memcpy ci-dessus. La fonction memcpy doit faire attention à la fonction memmove. Elle ne sera pas répétée ici, hehe.

2. Un autre point à noter à propos de la fonction memmove est qu'elle doit analyser comment la copier afin qu'elle ne se chevauche pas. Voici un schéma :

Cas 1 : dest est inférieur ou égal à l'adresse de src

Copiez d'avant en arrière comme ci-dessous afin qu'il n'y ait pas de chevauchement.

 Cas 2 : L'adresse de dest est supérieure à scr

Copiez de l'arrière vers l'avant comme ci-dessous afin qu'il n'y ait pas de chevauchement.

 2. Mise en œuvre de la simulation

#include<stdio.h>
#include<assert.h>
//模拟实现memmove
void* my_memmove(void* dest, const void* scr, size_t count)
{
	assert(dest && scr);//断言传进来的地址不是空指针
	void* ret = dest; //保存目标起始地址
	if (dest <= scr)//从前往后拷贝
	{
		while (count--)
		{
			*(char*)dest = *(char*)scr;
			(char*)dest = (char*)dest + 1;
			(char*)scr = (char*)scr + 1;
		}
	}
	else//从后往前拷贝
	{
		while (count--)
		{
			*((char*)dest + count) = *((char*)scr + count);
		}
	}
	return ret;
}





//应用模拟实现的函数
int main()                  
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	my_memmove(arr + 2, arr, 24);//预期出现结果为1 2 1 2 3 4 5 6 9 10
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);//实际出现结果
	}
	return 0;
}

  résultat de l'opération


Résumer

C'est tout le contenu pour aujourd'hui. Si vous le trouvez utile, n'oubliez pas d'aimer et de suivre. Merci pour votre soutien. Enfin, je souhaite que les étudiants diplômés puissent aller à terre et que les étudiants à la recherche d'un emploi puissent entrer Dachang.

Je suppose que tu aimes

Origine blog.csdn.net/qq_64042727/article/details/123714965
conseillé
Classement