Aritmética del puntero: ++ * ptr o * ptr ++?

Estoy aprendiendo el lenguaje C y confundí las diferencias entre ++*ptr y *ptr++ .

Por ejemplo:

 int x = 19; int *ptr = &x; 

Sé que ++*ptr y *ptr++ producen resultados diferentes, pero no estoy seguro de por qué es eso?

Estas declaraciones producen resultados diferentes debido a la forma en que los operadores se unen. En particular, el operador del prefijo ++ tiene la misma precedencia que * , y lo asocian de derecha a izquierda. Así

 ++*ptr 

es analizado como

 ++(*ptr) 

que significa “incrementar el valor apuntado por ptr “. Por otro lado, el operador postfix ++ tiene una precedencia mayor que el operador dereferrence * . El delantero

 *ptr++ 

medio

 *(ptr++) 

lo que significa “evaluar el valor señalado actualmente por ptr e incrementar el valor de ptr ” (cuyo orden no está especificado).

En el contexto que describió, probablemente quiera escribir ++*ptr , que ++*ptr x indirectamente a través de ptr . Escribir *ptr++ sería peligroso porque marcharía ptr allá de x , y como x no es parte de una matriz, el puntero estaría colgando en algún lugar de la memoria (¡tal vez encima de sí mismo!)

¡Espero que esto ayude!

La respuesta aceptada no es correcta. No es el caso que el operador postfix ++ tenga la misma precedencia que dereference / indirection * . Los operadores de prefijo y postfijo tienen una precedencia diferente, y solo el operador de prefijo tiene la misma precedencia que la desreferencia / indirección.

Como muestra la tabla de precedencia , postfix ++ tiene una precedencia mayor que dereference / indirection * . Entonces *ptr++ se evalúa como *(ptr++) . ptr++ evalúa el valor actual de ptr ; incrementa ptr solo como un efecto secundario. El valor de la expresión es el mismo que el valor actual de ptr . Por lo tanto, no tendrá ningún efecto sobre el valor almacenado en el puntero. Simplemente desreferenciará el puntero (es decir, obtendrá el valor actual almacenado allí, que es 19), luego avanzará el puntero. En su ejemplo, no hay un valor definido almacenado en la nueva posición de ptr , por lo que el puntero apunta a la basura. Desreferenciarlo ahora sería peligroso.

También como muestra la tabla, prefijo ++ tiene la misma precedencia que dereference / indirection * , pero debido a la asociatividad de derecha a izquierda, se evalúa como ++(*ptr) . Esto desreferenciará primero el puntero (es decir, obtendrá el valor almacenado en la dirección apuntada) y luego incrementará ese valor. Es decir, el valor ahora será 20.

La respuesta aceptada es correcta sobre los efectos de los dos, pero el mecanismo real es diferente del que se da allí.

Como dice templatetypedef, pero debe proporcionar el paréntesis alrededor de *ptr para garantizar el resultado. Por ejemplo, lo siguiente produce 1606415888 usando GCC y 0 usando CLang en mi computadora:

 int x = 19; int *ptr = &x; printf("%d\n", *ptr++); printf("%d\n", *ptr); 

Y esperabas que x fuera 20. Entonces usa (*ptr)++ lugar.