Tengo una pregunta que surge de esta discusión: C - modificar la dirección de un puntero pasado a una función
Digamos que tengo el siguiente código:
#include <stdio.h> foo(char **ptr){ *ptr++; } int main() { char *ptr = malloc(64); char arr[] = "Hello World!"; memcpy(ptr, arr, sizeof(arr)); foo(&ptr); foo(&ptr); printf("%s",ptr); return 0; } Me preguntaba cuál sería el resultado de este programa y pensé que debería ser llo World! .
Después de investigar un poco, encontré la pregunta vinculada anteriormente y me di cuenta de que, en C, los parámetros a las funciones siempre se pasan por valor . Hasta ahora no hubo problema. Cuando se trata de cambiar *ptr++; expresión a -> *ptr = *ptr +1; la salida se convierte en: llo World! .
En este punto, puedo decir que estoy un poco confundido. Para cambiar la dirección del puntero, necesitamos un puntero doble. Eso está bien, pero ¿por qué difieren las operaciones de incremento posterior? ¿Es por la precedencia del operador?
Aquí probé el ejemplo en un compilador de C en línea.
El operador de incremento de sufijo ++ tiene mayor precedencia que el operador de desreferencia * . Así que esto:
*ptr++;Se analiza como:
*(ptr++);Entonces cambia el valor del parámetro en sí, no lo que apunta. En cambio, quieres:
(*ptr)++;Los operadores de posfijo tienen mayor prioridad que los operadores unarios. Entonces esta expresión
*ptr++es equivalente a
*( ptr++ ) El valor de la ptr++ es el valor del puntero antes de que se incremente.
Entonces, en realidad está incrementando el parámetro ptr que tiene el tipo char ** . Entonces este incremento no cambia el puntero original y no tiene sentido.
En su lugar, podrías escribir
( *ptr )++Pero será más claro y menos confuso usar el operador de incremento unario como
++*ptrsi desea incrementar el propio puntero original.
Como han explicado otros, ++ es más importante (tiene una prioridad más alta) que * , por lo que su función foo en realidad se compiló así:
foo (char **ptr) { ptr = ptr + 1; // This modifies the parameter, which is a copy of a variable, copied *specifically* for this function; hence, modifying it will have no effect outside of the function. *ptr; // This is just an expression; it doesn't actually do anything, as the compiler would tell you if you wrote it this way. } Si cambia *ptr++ a (*ptr)++ , la función funcionará así:
foo (char **ptr) { *ptr = *ptr + 1; // Sets the variable pointed to by ptr to be equal to itself plus one. }