¿Post-incremento en un puntero desreferenciado?

Resuelto ChristopheD asked hace 15 años • 13 respuestas

Al intentar comprender el comportamiento de los punteros en C, me sorprendió un poco lo siguiente (código de ejemplo a continuación):

#include <stdio.h>

void add_one_v1(int *our_var_ptr)
{
    *our_var_ptr = *our_var_ptr +1;
}

void add_one_v2(int *our_var_ptr)
{
    *our_var_ptr++;
}

int main()
{
    int testvar;

    testvar = 63;
    add_one_v1(&(testvar));         /* Try first version of the function */
    printf("%d\n", testvar);        /* Prints out 64                     */
    printf("@ %p\n\n", &(testvar));

    testvar = 63;
    add_one_v2(&(testvar));         /* Try first version of the function */
    printf("%d\n", testvar);        /* Prints 63 ?                       */
    printf("@ %p\n", &(testvar));   /* Address remains identical         */
}

Producción:

64
@ 0xbf84c6b0

63
@ 0xbf84c6b0

¿Qué hace exactamente la *our_var_ptr++declaración en la segunda función ( add_one_v2) ya que claramente no es lo mismo que *our_var_ptr = *our_var_ptr +1?

ChristopheD avatar May 14 '09 02:05 ChristopheD
Aceptado

Este es uno de esos pequeños problemas que hacen que C y C++ sean tan divertidos. Si quieres dominar tu cerebro, descubre esto:

while (*dst++ = *src++) ;

Es una copia de cadena. Los punteros siguen incrementándose hasta que se copia un carácter con un valor de cero. Una vez que sepa por qué funciona este truco, nunca más olvidará cómo funciona ++ con los punteros.

PD: Siempre puedes anular el orden de los operadores con paréntesis. Lo siguiente incrementará el valor señalado, en lugar del puntero en sí:

(*our_var_ptr)++;
Mark Ransom avatar May 13 '2009 19:05 Mark Ransom

Debido a las reglas de precedencia de operadores y al hecho de que ++es un operador de sufijo, add_one_v2()se elimina la referencia al puntero, pero ++en realidad se aplica al puntero mismo . Sin embargo, recuerde que C siempre usa el paso por valor: add_one_v2()está incrementando su copia local del puntero, lo que no tendrá ningún efecto en el valor almacenado en esa dirección.

Como prueba, reemplácelo add_one_v2()con estos bits de código y vea cómo se ve afectado el resultado:

void add_one_v2(int *our_var_ptr)
{
    (*our_var_ptr)++;  // Now stores 64
}

void add_one_v2(int *our_var_ptr)
{
    *(our_var_ptr++);  // Increments the pointer, but this is a local
                       // copy of the pointer, so it doesn't do anything.
}
hbw avatar May 13 '2009 19:05 hbw

DE ACUERDO,

*our_var_ptr++;

funciona así:

  1. La desreferencia ocurre primero, brindándole la ubicación de memoria indicada por our_var_ptr(que contiene 63).
  2. Luego se evalúa la expresión, el resultado de 63 sigue siendo 63.
  3. El resultado se desecha (no se hace nada con él).
  4. our_var_ptrluego se incrementa DESPUÉS de la evaluación. Está cambiando hacia dónde apunta el puntero, no hacia dónde apunta.

Es efectivamente lo mismo que hacer esto:

*our_var_ptr;
our_var_ptr = our_var_ptr + 1; 

¿Tener sentido? La respuesta de Mark Ransom tiene un buen ejemplo de esto, excepto que en realidad usa el resultado.

BIBD avatar May 13 '2009 19:05 BIBD