pointer - Diferencia entre*ptr+= 1 y*ptr++ en C
p++ php (5)
* ptr + = 1: aumenta los datos a los que apunta ptr. * ptr ++: Incrementa el puntero que apunta a la siguiente ubicación de memoria en lugar de los datos a los que apunta el puntero.
Recién comencé a estudiar C, y al hacer un ejemplo sobre pasar puntero a puntero como parámetro de una función, encontré un problema.
Este es mi código de muestra:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int* allocateIntArray(int* ptr, int size){
if (ptr != NULL){
for (int i = 0; i < size; i++){
ptr[i] = i;
}
}
return ptr;
}
void increasePointer(int** ptr){
if (ptr != NULL){
*ptr += 1; /* <----------------------------- This is line 16 */
}
}
int main()
{
int* p1 = (int*)malloc(sizeof(int)* 10);
allocateIntArray(p1, 10);
for (int i = 0; i < 10; i++){
printf("%d/n", p1[i]);
}
increasePointer(&p1);
printf("%d/n", *p1);
p1--;
free(p1);
fgets(string, sizeof(string), stdin);
return 0;
}
El problema ocurre en la línea 16, cuando
*ptr+=1
a
*ptr++
.
El resultado esperado debería ser la matriz completa y el número 1, pero cuando uso
*ptr++
el resultado es 0.
¿Hay alguna diferencia entre
+=1
y
++
?
Pensé que los dos son lo mismo.
Apliquemos paréntesis para mostrar el page
a + b / c
a + (b/c)
Hagámoslo de nuevo con
*ptr += 1
(*ptr) += 1
Y de nuevo con
*ptr++
*(ptr++)
-
En
*ptr += 1
, incrementamos el valor de la variable a la que apunta nuestro puntero. -
En
*ptr++
, incrementamos el puntero después de completar toda nuestra declaración (línea de código) y devolvemos una referencia a la variable a la que apunta nuestro puntero.
Este último te permite hacer cosas como:
for(int i = 0; i < length; i++)
{
// Copy value from *src and store it in *dest
*dest++ = *src++;
// Keep in mind that the above is equivalent to
*(dest++) = *(src++);
}
Este es un método común utilizado para copiar una matriz
src
en otra matriz
dest
.
El orden de precedencia para los 3 operadores involucrados en su pregunta es el siguiente:
post-incremento
++
> desreferencia
*
> asignación
+=
Puede consultar esta page para obtener más detalles sobre el tema.
Al analizar una expresión, un operador que aparece en una fila estará más ajustado (como entre paréntesis) a sus argumentos que cualquier operador que esté en una fila más abajo. Por ejemplo, la expresión
*p++
se analiza como*(p++)
y no como(*p)++
.
En pocas palabras, para expresar esta asignación
*ptr+=1
utilizando el operador posterior al incremento, debe agregar paréntesis al operador de desreferencia para dar prioridad a esa operación sobre
++
como en este
(*ptr)++
La diferencia se debe a la precedencia del operador.
El operador posterior al incremento
++
tiene mayor prioridad que el operador de desreferencia
*
.
Entonces
*ptr++
es equivalente a
*(ptr++)
.
En otras palabras, el incremento posterior modifica el puntero, no lo que apunta.
El operador de asignación
+=
tiene menor prioridad que el operador de desreferencia
*
, por lo tanto
*ptr+=1
es equivalente a
(*ptr)+=1
.
En otras palabras, el operador de asignación modifica el valor al que apunta el puntero y no cambia el puntero en sí.
Muy buena pregunta
En K&R "Lenguaje de programación C" "5.1 Punteros y Direcciones", podemos obtener una respuesta para esto.
"Los operadores unarios * y & se unen más estrechamente que los operadores aritméticos"
*ptr += 1 //Increment what ptr points to.
"Los operadores unarios como * y ++ se asocian de derecha a izquierda ".
*ptr++ //Increment prt instead of what ptr point to.
// Funciona como * (ptr ++).
La forma correcta es:
(*ptr)++ //This will work.