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

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() lugar de:

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

¿Alguien puede explicarlo?

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

 *p++ 

significa desreferenciar el puntero, luego incrementar el puntero mismo en 1 (como suele ocurrir, de acuerdo con las reglas de la aritmética del puntero, no es necesariamente un byte, sino más bien sizeof(*p) respecto a la dirección resultante). Por otra parte,

 *p += 1 

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

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

La precedencia del prefijo ++ y * es igual. La asociatividad de ambos es de derecha a izquierda. La precedencia de postfix ++ es más alta que ambas * y prefix ++. La asociatividad de postfix ++ es de izquierda a derecha.

Empecemos con *p += 1

Trataré de 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 la desreferenciación y + = 1 para el incremento. El paso 2 que tiene la precedencia más alta * tiene la precedencia más alta sobre + =


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

Paso 1 Veamos los operadores y los operandos: En este caso, es el operando, y usted tiene dos operadores, en este caso * para la eliminación de referencias y ++ para el incremento. Paso 2, que tiene la precedencia más alta? ++ tiene mayor prioridad sobre * Nota: incluso si tienen la MISMA precedencia que asocian de derecha a izquierda, de nuevo, ++ está antes de * Paso 3 (la parte difícil …) ¿Dónde está ++? está en el lado derecho del operando, lo que significa Incremento de POST En este caso, el comstackdor toma una ‘nota mental’ para realizar el incremento DESPUÉS de que se haga con todos los demás operadores … ¿Qué significa después? Significa que solo aplicará el incremento como el último paso antes del siguiente ‘;’ así que se hará con todos los demás operadores que están en la misma ‘línea’. Nota: si era * ++ p, 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 mantendrá el valor del dereferenciado * p y el otro mantendrá el valor del incremento p ++, la razón en este caso son dos, es la actividad POST … Aquí es donde en este caso Es complicado, y parece una contradicción. Uno esperaría que el ++ tenga prioridad sobre el *, lo que hace, solo que el POST significa que se aplicará solo después de TODOS los demás operandos, ANTES de la siguiente ‘;’ simbólico…

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