2012-08-31 31 views
46

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

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 

Puede alguien explicar?

+22

porque '* p ++' es el mismo que '* (p ++)' –

+5

[precedencia de los operadores] (http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence) – chris

+3

también intente 'void foo3 (char ** p) {(* p) ++; } ' –

Respuesta

95

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

*p++ 

significa eliminar la referencia al puntero, a continuación, incrementar el puntero por 1 (como se generalmente, de acuerdo con las reglas de la aritmética del puntero, no es necesariamente un byte, sino más bien sizeof(*p) con respecto a la dirección resultante). Por otro lado,

*p += 1 

medios incrementan el valor apuntado por el puntero por uno (y no hacen nada con el puntero en sí).

+8

Has hecho un gran trabajo al explicarlo, pero podrías agregar un detalle * p ++ incrementa el puntero en 1" unidad ", por lo que un puntero podría incrementarse en uno , mientras que un puntero int puede incrementarse en 4, etc., dependiendo de los detalles de la implementación. –

+3

@EdwinBuck: Realmente no veo la relevancia, es solo la aritmética del puntero normal y no el foco de la pregunta. – GManNickG

+5

@EdwinBuck si un puntero es 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. –

29

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

0

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

0

Vamos a empezar con *p += 1

voy a tratar de responder a esta de un poco de un ángulo diferente ... mirada Paso 1 Vamos a los operadores y los operandos: En este caso, es un operando (el puntero p), y tenemos dos operadores, en este caso * para desreferencia y + = 1 para incremento. Paso 2, que tiene la mayor precedencia * tiene mayor precedencia sobre + =


*P++ Éste es un poco más complicado ... tal vez incluso malvados De nuevo tenemos un operando (p puntero) y dos operadores, solo ahora el * para la desreferencia y el incremento ++ post tienen la misma precedencia. (En algunas tablas el ++ en una publicación es una precedencia 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 desreferenciación y ++ para incremento. Paso 2, que tiene la precedencia más alta? ++ tiene una precedencia mayor que * Nota: incluso si tienen la MISMA precedencia que asocian de derecha a izquierda, de nuevo, ++ está antes de * Paso 3 (la parte complicada ...) ¿Dónde está ++? que es el lado derecho del operando, lo que significa Incremento POSTAL En este caso, el compilador toma una 'nota mental' para llevar a cabo el incremento DESPUÉS se hace con todos los demás operadores ... Lo que después de los medios ?Significa que solo aplicará el incremento como el último paso antes del siguiente ';' entonces 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 que cualquier otro operador en la misma línea, en este caso, es equivalente a tomando dos del registro del procesador, uno mantendrá el valor de la desreferenciada * p y el otro mantendrá el valor del p ++ incrementado, 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 del siguiente ';' token ...

Como dije, la parte engañosa es que cualquier incremento que esté a la derecha de un operando se apartará, y se aplicará como la ÚLTIMA operación antes de pasar a la siguiente línea. .

Cuestiones relacionadas