39 votes

Peut memcpy ou memmove retourner un pointeur différent que dest?

La fonction memmove est définie comme ceci:

void *memmove(void *dest, const void *src, size_t n);

Dans le Linux page de manuel, il est dit:

VALEUR DE RETOUR
Le memmove() renvoie un pointeur vers dest.

Pourquoi n'est-ce pas la fonction définie comme void memmove(…) lorsqu'il renvoie toujours l'un des paramètres d'entrée? Peut la valeur de retour sera différent de dest?

Ou est la valeur de retour vraiment toujours dest et il est juste fait pour être en mesure de composer de la fonction dans certains des façons créatives?

43voto

dasblinkenlight Points 264350

memmove ne sera jamais rien d'autre qu' dest.

De retour dest, plutôt que de faire des memmove nulle, est utile quand le premier argument est une expression calculée, car elle permet d'éviter le calcul de la même valeur dès le départ, et le stocker dans une variable. Cela vous permet de le faire en une seule ligne

void *dest = memmove(&buf[offset] + copiedSoFar, src + offset, sizeof(buf)-offset-copiedSoFar);

ce que vous auriez besoin de faire sur deux lignes:

void *dest = &buf[offset] + copiedSoFar;
memmove(dest, src + offset, sizeof(buf)-offset-copiedSoFar);

26voto

Sourav Ghosh Points 54713

Comme par C11, au chapitre §7.24.2.1 et §7.24.2.2

void *memcpy(void * restrict s1, const void * restrict s2, size_t n);

[...] L' memcpy fonction retourne la valeur d' s1.

et,

void *memmove(void *s1, const void *s2, size_t n);

[...] L' memmove fonction retourne la valeur d' s1.

Ainsi, les fonctions seront toujours retourner le pointeur vers le tampon de destination, c'est par la conception.

Sur le pourquoi de la partie, de nombreuses fonctions sont conçues de cette manière de faire de chaînage des appels de fonction possible. De cette façon, vous pouvez avoir un appel à l' memmove() comme argument d'une autre fonction, où la valeur copiée (j'.e, le pointeur dest) va être de quelque utilité.

Par exemple, vous pouvez écrire le plus court

 puts(memmove(dest_buffer, src_buffer, welcome_message_size));

au lieu de la plus longue

 memmove(dest_buffer, src_buffer, welcome_message_size);
 puts(dest_buffer);

13voto

AndreyT Points 139512

L'idiome de retourner la valeur exacte de l'un des arguments (de type pointeur) il existe dans le but de soutenir "l'enchaîné" appels de fonction (voir aussi strcpy, strcat etc). Il vous permet d'écrire un code répétitif comme une seule expression de la déclaration au lieu de le diviser en plusieurs états. Par exemple

char buffer[1024];
printf("%s\n", strcat(strcat(strcpy(buffer, "Hello"), " "), "World"));

struct UserData data_copy;
some_function(memcpy(&data_copy, &original_data, sizeof original_data));

Même si vous n'aimez pas ce style d'organisation de code et préfèrent faire de même à travers plusieurs états, la surcharge de retour d'un [inutile] la valeur du pointeur est pratiquement inexistante.

On peut même dire que la valeur de cet idiome a augmenté un peu après l'introduction de littéraux composés en C99. Avec un composé de lterals cette très idiome permet d'écrire le même code sans introduire un nom de variable intermédiaire

printf("%s\n", strcat(strcat(strcpy((char [1024]) { 0 }, "Hello"), " "), "World!"));

some_function(memcpy(&(struct UserData) { 0 }, &original_data, sizeof original_data));

ce qui est logique, puisque dans la plupart des cas, le nom de variable est supposée être de courte durée, n'est pas nécessaire après, et seulement encombre l'espace de noms.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X