La aritmética de punteros es una característica fundamental del lenguaje C, que hace que el trabajo con memoria sea flexible, pero también potencialmente peligroso.
La aritmética de punteros surgió debido a las características de los lenguajes de bajo nivel y está orientada al trabajo con arreglos y al tratamiento de datos estructurados directamente en la memoria. En C, todos los punteros "conocen" el tamaño del tipo al que apuntan.
Muchos desarrolladores cometen el error de pensar que al sumar uno a un puntero, la dirección aumentará exactamente en un byte. En realidad, el incremento ocurre en sizeof(tipo). Al trabajar con diferentes tipos de datos, especialmente con estructuras de diferentes tamaños, es fácil cometer errores al navegar por la memoria. Además, la aritmética de punteros no está permitida con void* — este es un error estándar.
Todas las operaciones aritméticas con punteros tienen en cuenta el tamaño del tipo correspondiente, lo que hace que las operaciones con arreglos sean lo más eficientes posible. Por ejemplo:
#include <stdio.h> int arr[4] = {10, 20, 30, 40}; int *p = arr; printf("%d\n", *(p + 2)); // Imprimirá 30
Aquí (p + 2) desplaza el puntero 2 * sizeof(int) bytes hacia adelante, y no simplemente 2 bytes.
Características clave:
¿Se puede realizar operaciones de incremento/decremento con punteros a void?
No, el estándar C prohíbe la aritmética con void*. Primero, es necesario convertir el puntero a un tipo concreto, por ejemplo (char*), y luego realizar la aritmética.
void *vp = arr; char *cp = (char *)vp; cp++;
¿Qué sucederá si se suma a un puntero a una estructura o arreglo un valor que exceda el tamaño del arreglo?
Esto llevará a salirse de los límites del área de memoria permitida (comportamiento indefinido). C no verifica los límites de los arreglos; la responsabilidad recae en el programador.
¿Se pueden sumar dos punteros entre sí directamente?
No, la suma de punteros está prohibida y no tiene sentido. Solo se permite la resta de dos punteros que pertenecen al mismo arreglo.
Un joven desarrollador, trabajando con un arreglo de int a través de punteros, desplazó el puntero por un número fijo de bytes, olvidando el tamaño del tipo.
Ventajas:
Desventajas:
Un desarrollador experimentado siempre utiliza expresiones como (ptr + n), confiando en que el compilador escalará el desplazamiento según el tamaño del tipo.
Ventajas:
Desventajas: