C – modificar la dirección de un puntero pasado a una función

No entiendo por qué la modificación de la dirección del pointer pasada como parameter a una function no se mantiene fuera de esta función (la dirección de ptr no cambia después de que se llama a esta función):

 void advance(int *ptr) { ptr = ptr + 1 } 

Cuando pueda dentro de esta misma función, modificar el value apuntado por ptr : *ptr = *ptr + 1 .

PD: Sé que puedo lograr lo que quiero usando un pointer to a pointer : **ptr .

Como C no es llamada por referencia, siempre es llamada por valor, incluso con referencias / punteros como argumentos .

No es como otros idiomas, donde puede diferenciar entre tipos de argumentos.

Este comportamiento se debe a que los parámetros a las funciones en C siempre se pasan por valor . Lo que estás pasando por valor aquí es una dirección. Cuando modifica ptr está modificando una copia del valor de la persona que llama.

Para modificar el valor de la persona que llama, necesita un nivel adicional de direccionamiento indirecto:

 void advance(int **ptr) { *ptr = *ptr + 1; } 

Cuando define la función void advance (int * ptr) significa que se creará un puntero en la stack, que apunta a la misma dirección que el puntero original. Para ver la prueba, intente imprimir la dirección del puntero de origen (& orig) y la dirección del puntero de parámetro (& param), y las direcciones de “apuntado a” (orig, param). Las direcciones de puntero serán diferentes, pero las direcciones apuntadas serán las mismas.

Entonces, tenemos dos punteros que apuntan a la misma área, si modifica el parámetro, apuntará a la nueva área, pero el valor original no se cambiará, sino que apunta a la misma área que antes.

Es por eso que necesitas un puntero a un puntero. Si usa un puntero a un puntero (int ** ppointer = & orig), tendrá un puntero que apunta directamente al área donde orig almacena la dirección “apuntada a” (a donde apunta el orig actualmente). Al cambiar el valor del puntero *, también cambiará directamente el valor del origen.

Realmente respondiste tu propia pregunta;)

la modificación de la dirección del puntero pasada como parámetro a una función no se mantiene fuera de esta función

Dentro de la función está administrando una copia de su parámetro. Puede modificar el valor apuntado porque está solicitando explícitamente un cambio en una dirección específica.

 void advance(int *ptr) 

la llamada a la función creará una nueva variable en la stack llamada ptr (en la stack de la función avanzada), que es un puntero a un entero, incrementándola dentro de la función solo funcionará mientras esté dentro de la función advace, una vez que salga La función de avance, la variable se pierde. La stack de la función de avance ya no existe.

 ****** / --- \
 * 20 * ----> |  2 |
 ****** \ --- /
   i 20-24

Aquí i es un puntero que apunta a la ubicación de memoria 20 que tiene un valor 2 es decir, cuando los datos binarios en 20 + sizeof(int) - 1 se interpretan como un número decimal. Ahora, cuando pasa i para advance , que tiene un argumento ptr , lo que realmente sucede es

 ****** / --- \ ******
 * 20 * ----> |  2 |  <---- * 20 *
 ****** \ --- / ******
   i 20-24 ptr

ptr = i; es decir, el valor de i se establece en el valor de ptr , que en realidad son direcciones aquí, ya que i y ptr son punteros.

Cuando incrementas ptr , solo hará que el puntero apunte a una dirección diferente y no cambie nada con respecto a i ya que ptr es una copia y no i mismo. Sin embargo, si cambia el valor en ptr utilizando el operador * es decir, como *ptr = 10 ; entonces el 2 anterior cambiará a 10 tanto también cambiará *i , que también apunta a 20. Una vez más, observe que la dirección o el valor de i están intactos, solo la ubicación a la que apunta sufrió un cambio. Si hubiera habido 10 punteros apuntando a la dirección 20 , incluso entonces ninguno de ellos cambia, pero todo su valor apuntado se modifica.

Ver la función:

 void demonstrate(int num) { num = num + 1; // type of num is int } // destroys "num", because num's scope is only "demonstrate" function 

En su función:

 void advance(int *ptr) { ptr = ptr + 1; // type of ptr is int* and ptr is incremented } // destroys "ptr" for the similar reason 

Pero desea una función que modifique una dirección ( puntero IN ). Así que la solución completa debe ser:

 #include  void advance(int **ptr) { //ptr is a pointer to a pointer // so *ptr is the pointer that is pointed by ptr *ptr = *ptr + 1; // incrementing the address IN the pointer pointed by ptr } // destroys "ptr" for the reason above int main() { int x = 5; // initially assign "ptrToChange" int *ptrToChange = &x; // "ptrToChange" now points to x // passing address OF "ptrToChange" to "advance" function advance(&ptrToChange); // now "ptrToChange" does NOT point to x return 0; }