¿Por qué *p++ es diferente de *p += 1?

5 minutos de lectura

¿Por que p es diferente de p 1
Jack

Considerar:

void foo1(char **p) { *p++; }
void foo2(char **p) { *p += 1; }

y

char *s = "abcd";
char *a = s; 
foo1(&a); 
printf("%s", a); //abcd

pero si uso foo2() en lugar de:

char *a = s; 
foo2(&a); 
printf("%s", a); //bcd

¿Alguien puede explicarlo?

  • Porque *p++ es lo mismo que *(p++)

    –Paul Tomblin

    31 de agosto de 2012 a las 19:25

  • precedencia del operador

    – chris

    31 de agosto de 2012 a las 19:25


  • Intenta también void foo3(char **p) { (*p)++; }

    – Michael Burr

    31 de agosto de 2012 a las 20:34

  • disfrute de su agradable insignia de pregunta 🙂

    –Ricky Gummadi

    12 de octubre de 2012 a las 3:49

La clave es la precedencia de la += y el ++ operador. los ++ tiene mayor precedencia que el += (de hecho, los operadores de asignación tienen la segunda precedencia más baja en C), por lo que la operación

*p++

significa desreferenciar el puntero, luego incrementar el puntero sí mismo por 1 (como suele ser, de acuerdo con las reglas de la aritmética de punteros, no es necesariamente un byte, sino más bien sizeof(*p) respecto a la dirección resultante). Por otro lado,

*p += 1

significa incrementar el valor señalado por el puntero por uno (y no hacer nada con el puntero en sí).

  • Hiciste un gran trabajo al explicarlo, pero podrías agregar un detalle * p ++ incrementa el puntero en 1 “unidad”, por lo que un puntero char podría incrementarse en uno, mientras que un puntero int podría incrementarse en 4, etc. dependiendo de las especificaciones de implementación.

    – Edwin Buck

    31 de agosto de 2012 a las 19:27

  • @EdwinBuck: Realmente no veo la relevancia, eso es solo aritmética de puntero normal y no el enfoque de la pregunta.

    – GManNickG

    31 de agosto de 2012 a las 19:29

  • @EdwinBuck, ya sea que un puntero sea un int o un char, cuando lo incrementa, aumenta en uno. La dirección real que representa ese puntero puede cambiar más de un byte, sin embargo, debido al tamaño del puntero.

    – Ricardo J. Ross III

    31/08/2012 a las 19:30

  • @RichardJ.RossIII Ambos tenemos razón, pero estamos hablando de diferentes 1. Una unidad, o sizeof(*p) sigue siendo un 1 en alguna escala, pero si observa el valor binario almacenado en p el valor real no siempre será “+1” en aritmética binaria.

    – Edwin Buck

    31 de agosto de 2012 a las 19:41

  • La representación del puntero, que es la dirección de memoria simple en muchas implementaciones de C, no debe confundirse con su valor, que es su significado en el contexto de C. p++ aumenta el valor en uno. Su efecto sobre la representación de ese valor es irrelevante para los propósitos de esta pregunta, de la misma manera que es irrelevante que sumar 1 al flotante 1.f normalmente cambia la representación por 8.388.608.

    –Eric Postpischil

    31 de agosto de 2012 a las 20:10

Precedencia. el postfijo ++ se une más fuerte que el prefijo * por lo que incrementa p. los += está en el extremo inferior de la lista de precedencia, junto con el operador de asignación simple, por lo que suma 1 a *p.

La precedencia del prefijo ++ y * es la misma. La asociatividad de ambos es de derecha a izquierda. La precedencia del sufijo ++ es mayor que la de * y el prefijo ++. La asociatividad de postfix ++ es de izquierda a derecha.

¿Por que p es diferente de p 1
G. Simsic

Empecemos con *p += 1

Intentaré responder esto desde un ángulo un poco diferente… Paso 1 Veamos los operadores y los operandos: En este caso es un operando (el puntero p), y tenemos dos operadores, en este caso * para desreferenciar y += 1 para incremento. El paso 2 que tiene mayor precedencia * tiene mayor precedencia sobre +=


*P++

Este es un poco más complicado… tal vez incluso perverso Nuevamente tenemos un operando (p el puntero) y dos operadores, solo que ahora el * para la desreferencia y el incremento de post ++ tienen la misma precedencia. (En algunas tablas, el ++ en una publicación tiene una prioridad más alta).

Paso 1 Veamos los operadores y los operandos: En este caso es el operando, y tienes dos operadores, en este caso * para desreferenciar y ++ para incrementar. Paso 2, ¿cuál tiene mayor prioridad? ++ tiene mayor precedencia sobre * Nota: incluso si tienen la MISMA precedencia se asocian de derecha a izquierda, de nuevo, ++ está antes de * Paso 3 (la parte complicada…) ¿Dónde está ++? está a la derecha del operando, lo que significa Incremento POST En este caso, el compilador toma una ‘nota mental’ para realizar el incremento DESPUÉS se hace con todos los demás operadores… ¿Qué significa after? Significa que solo aplicará el incremento como el último paso antes del siguiente ‘;’ por lo que se hará con todos los demás operadores que están en la misma ‘línea’ nota: si era *++p entonces lo hará ANTES de cualquier otro operador en la misma línea por lo que en este caso es equivalente a tomar dos del registro del procesador, uno contendrá el valor de *p desreferenciado y el otro contendrá el valor de p++ incrementado, la razón por la que en este caso hay dos, es la actividad POST… Aquí es donde en este caso es complicado, y parece una contradicción. Uno esperaría que ++ tuviera prioridad sobre *, lo cual sucede, solo que POST significa que se aplicará solo después de TODOS los demás operandos, ANTES del siguiente ‘;’ simbólico…

Como dije, la parte complicada es que cualquier incremento que esté a la derecha de un operando se dejará de lado y se aplicará como la ÚLTIMA operación antes de pasar a la siguiente línea…

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad