III. c_memcpy▲
III-A. Prototype▲
void
*
c_memcpy (
void
*
dest, const
void
*
src, c_size_t n);
III-B. Description et comportement▲
La fonction c_memcpy copie n octets en partant du début de l'adresse src vers l'adresse dest (en partant également du début de cette adresse).
La fonction a un comportement indéterminé si les deux adresses se chevauchent et ont donc des parties communes. Dans ce cas il est préférable d'utiliser la fonction c_memmove !
L'adresse dest est renvoyée à la fin de la fonction.
III-C. Algorithme▲
Voici un algorithme possible pour la fonction c_memcpy :
algorithme
fonction c_memcpy (dest:générique, src:générique, n:entier):générique
début
i <- 0
tant que n <- n - 1 faire
dest[i] <- src[i]
i <- i + 1
ftant
retourne dest
fin
lexique
dest : générique : Zone mémoire de destination d'un type quelconque.
src : générique : Zone mémoire source d'un type quelconque.
n : entier : Longueur de la copie.
i : entier : Variable d'incrémentation.
L'algorithme est simple : nous décrémentons directement la valeur de l'argument n (en effet, il n'y a pas de remontée dans la variable d'origine étant donné que sa valeur est copiée, cela peut par contre changer suivant les langages, mais c'est le cas en C). La boucle parcourt donc les adresses tant que n > 0.
Dans la boucle on copie simplement l'octet courant de l'adresse src vers l'adresse dest puis nous incrémentons i !
On termine par retourner l'adresse dest tel qu'il est écrit dans la description de la fonction et donc dans la norme.
Complexité temporelle dans le pire des cas: |
---|
Parcours simple de la boucle n fois: complexité en O(n) |
III-D. Implémentation▲
void
*
c_memcpy (
void
*
dest, const
void
*
src, c_size_t n)
{
char
*
p_dest =
dest;
const
char
*
p_src =
src;
while
(
n--
)
{
*
p_dest++
=
*
p_src++
;
}
return
dest;
}
L'implémentation est adaptée au Langage C, les arguments étant de type void *, il nous faut les convertir en type char *. En effet, le type char vaut par définition 1 octet, et ce, quelle que soit l'implémentation du système. Cela convient très bien étant donné que nous voulons copier les adresses octet par octet ! Nous déclarons donc des pointeurs sur char pour stocker le début de chaque adresse.
La condition de la boucle ne change pas, nous décrémentons directement l'argument, ce que nous pouvons faire vu qu'il n'y a pas de remontée au-delà de l'argument, cela évite une déclaration de variable supplémentaire.
Le bloc de la boucle copie tout simplement l'octet courant pointé par *p_src vers l'emplacement pointé par *p_dest puis nous incrémentons chacune des adresses vers l'emplacement suivant.
On termine en retournant le début de l'adresse dest !
III-E. Tests▲
#include "c_string.h"
#include <stdio.h>
int
main (
void
)
{
const
char
*
str1 =
"
Bonjour, le monde !
"
;
char
str2 [15
] =
{
0
}
;
c_memcpy (
str2, str1, 7
);
printf (
"
str1 : %s
\n
"
, str1);
printf (
"
str2 : %s
\n
"
, str2);
return
0
;
}
Dans ce petit programme d'exemple, on copie la sous-chaine « Bonjour » de la chaine str1 vers le tableau str2 dont on initialise dès le départ tous les octets à 0 ce qui évitera des désagréments ! En effet, la fonction ne place pas de zéro de fin sauf s'il se trouve dans la longueur n donc si votre chaine de destination n'en possède pas vous aurez des bugs dans l'affichage et même sûrement un comportement indéterminé !
Voici la sortie sur la console :
str1 : Bonjour, le monde !
str2 : Bonjour
Process returned 0 (0x0) execution time : 0.015 s
Press any key to continue.