retornar punteros puntero matrices lenguaje estructura datos aritmetica c return-value function-call memmove

punteros - ¿Puede memcpy o memmove devolver un puntero diferente al de dest?



punteros y matrices en c (3)

La función memmove se define así:

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

En la página de manual de Linux, dice:

VALOR DEVUELTO
La función memmove () devuelve un puntero a dest.

¿Por qué la función no se define simplemente como void memmove(…) cuando siempre devuelve uno de los parámetros de entrada? ¿Puede el valor de retorno ser diferente de dest ?

¿O es que el valor de retorno realmente siempre se dest y solo se hace para poder componer la función de alguna manera creativa?


El idioma de devolver el valor exacto de uno de los argumentos (de tipo puntero) existe para admitir llamadas de función "encadenadas" (consulte también strcpy , strcat , etc.). Le permite escribir algo de código repetitivo como una sola expresión en lugar de dividirlo en varias declaraciones. Por ejemplo

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));

Incluso si no le gusta este estilo de organización de código y prefiere hacer lo mismo a través de varias declaraciones, la sobrecarga de devolver un valor de puntero [innecesario] es virtualmente inexistente.

Incluso se puede decir que el valor de este idioma aumentó un poco después de la introducción de los literales compuestos en C99. Con lterales compuestos, este mismo lenguaje permite escribir el mismo código sin introducir una variable intermedia nombrada

printf("%s/n", strcat(strcat(strcpy((char [1024]) { 0 }, "Hello"), " "), "World!")); some_function(memcpy(&(struct UserData) { 0 }, &original_data, sizeof original_data));

lo que tiene sentido, ya que en la mayoría de los casos se supone que la variable nombrada es de corta duración, no se necesita después, y solo desordena el espacio de nombres.


Según C11 , el capítulo §7.24.2.1 y §7.24.2.2

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

[...] La función memcpy devuelve el valor de s1 .

y,

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

[...] La función memmove devuelve el valor de s1 .

Por lo tanto, las funciones siempre devolverán el puntero al búfer de destino, eso es por diseño.

Ahora que llegamos a la parte de por qué , muchas funciones están diseñadas de esta manera para hacer posible el encadenamiento de llamadas a funciones. De esa manera, puede tener una llamada a memmove() como un argumento a otra función, donde el valor copiado ( es decir, el puntero a dest ) será de alguna utilidad.

Por ejemplo, puedes escribir el más corto.

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

en lugar del más largo

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


memmove nunca devolverá nada más que dest .

Devolver dest , en lugar de hacer memmove void, es útil cuando el primer argumento es una expresión computada, porque le permite evitar calcular el mismo valor por adelantado y almacenarlo en una variable. Esto te permite hacerlo en una sola línea.

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

lo que de otro modo necesitarías hacer en dos líneas:

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