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-chaîne "Bonjour"
de la chaîne 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 chaîne 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.