Diario de un
programador. Día 189
Operaciones de
aritmética con punteros en C.
Siguiendo con el
tema de los punteros en C, debemos mencionar que se pueden realizar ciertas
operaciones aritméticas con los punteros, por ejemplo. Se pueden sumar o
restar, debido a esto, se está permitido utilizar los incrementos ++ o
decrementos --
Cabe hacer
presente que estas operaciones solamente son válidas y tienen sentido cuando se
trabajan con arreglos. Vamos a mostrar algunos ejemplos para entender el por
qué.
Supongamos que
declaramos el siguiente arreglo:
int arreglo[10];
También vamos a
suponer, por cuestiones de hacerlo simple, que su primer elemento, o sea
arreglo[0], está en la posición de memoria 1000000.
Entonces,
crearemos un puntero que apunte a la primera posición del arreglo. Esto lo
lograríamos de la siguiente manera:
*pArreglo = &arreglo[0];
Entonces, al
tratar de hacer esto...
pArreglo++;
Es lo mismo que
estuviera haciendo pArreglo + 1 o en el caso de sumar en la memoria, estaría
sumando 1000000 + 1 (suponiendo como dijimos, que la posición estuviese en 1000000).
En aritmética
convencional, esto daría como resultado 1000001, pero no es el caso de los
punteros. En la aritmética de los punteros, lo que se suma (o resta según el
caso) es el tamaño del tipo de dato. Por lo general los enteros tienen un valor
de 4 bytes (en algunas máquinas valen 2 mientras que en otras valen 8). Por lo
tanto el resultado de esto sería 1000004, y si sumamos pArreglo +2 daría como
resultado 1000008, si sumamos +3 daría 1000012 y así sucesivamente. Entonces
esto sería algo así:
1000000 + 1 = 1000000 + (1 * 4) = 1000004
1000000 + 2 = 1000000 + (2 * 4) = 1000008
1000000 + 3 = 1000000 + (3 * 4) = 1000012
Con un dibujo quizás quede un poco más claro
Veamos un
ejemplo con un código. Voy a crear un arreglo de 5 elementos, luego los voy a
rellenar usando un ciclo for y luego veré en qué posición de memoria quedaron
alojados esos valores.
El código es el siguiente:
#include<stdio.h>
int main(void){
int arreglo[5];
int *pArreglo = &arreglo[0];
int i;
for (i = 0; i < 5;
i++){
//relleno el arreglo
con valores
arreglo[i] = i;
}
for (i = 0; i < 5;
i++){
//muestro la
posición de los valores
printf("%d\n",
&arreglo[i]);
}
return 0;
}
Al ejecutar este código estas son las posiciones de memoria que me
muestra en mi caso:
La primera termina en 508, luego sigue 512 y así
sucesivamente se va incrementando de 4 en 4, por lo que se deduce que en este
caso, el valor del entero es de 4 bytes.
Ahora voy a modificar este programa, añadiendo un
incremento al puntero pArreglo y luego mostraré el resultado. Esto es lo que me
muestra el programa:
#include<stdio.h>
int main(void){
int arreglo[5];
int *pArreglo = &arreglo[0];
int i;
for (i = 0; i < 5;
i++){
arreglo[i] = i;
}
for (i = 0; i < 5;
i++){
pArreglo++;
printf("%d ", &arreglo[i]);
printf("%d\n",
&pArreglo[i]);
}
return 0;
}
La columna de la izquierda es el valor original,
mientras que la columna de la derecha se ve el incremento que se realizó.
La primera posición se aumentó en 4 bytes, la segunda
en 8 y así sucesivamente quedando de la siguiente manera:
1 -> 4
2 -> 8
3 -> 12
4 -> 16
5 -> 20
Como mencioné anteriormente, en algunos computadores
los enteros son de 4 bytes, mientras que en otros son de 2 o de 8, pero ¿cómo
podemos saber el valor de los tipos de datos en nuestro equipo? En casos como
estos podemos utilizar el operador sizeof
el cual nos sirve para obtener el tamaño de un tipo de datos. Este operador
regresa un entero, el cual corresponde al número total del tamaño de bytes.
A continuación un ejemplo:
#include<stdio.h>
int main(void){
printf("int = %d\n", sizeof(int));
printf("short = %d\n",
sizeof(short));
printf("long = %d\n",
sizeof(long));
printf("char = %d\n",
sizeof(char));
printf("float = %d\n",
sizeof(float));
printf("double = %d\n",
sizeof(double));
printf("long double = %d\n",
sizeof(long double));
return 0;
}
Al compilar y ejecutar este programa, estos son los valores que me
muestra:
Dejaremos esto hasta aquí el día de hoy ya que aún hay mucho más que
ver con esto de los punteros.
Saludos.
Gustavo J. Cerda Nilo
Diciembre 2016