8.2. Punteros

Los punteros pueden ser constantes. El compilador pondrá más esfuerzo aún para evitar el almacenamiento y hacer expansión de constantes cuando se trata de punteros constantes, pero estas características parecen menos útiles en este caso. Lo más importante es que el compilador le avisará si intenta cambiar un puntero constante, lo que representa un buen elemento de seguridad. Cuando se usa const con punteros tiene dos opciones: se pueden aplicar a lo que apunta el puntero o a la propia dirección almacenada en el puntero. La sintaxis es un poco confusa al principio pero se vuelve cómodo con la práctica.

8.2.1. Puntero a constante

El truco con la definición de un puntero, al igual que con una definición complicada, es leerla empezando por el identificador e ir analizando la definición hacia afuera. El especificador const está ligado a la cosa «más cercana». Así que si se quiere impedir cambios en el elemento apuntado, escribe una definición parecida a esta:

const int* u;

Empezando por el identificador, se lee «u es un puntero, que apunta a un entero constante». En este caso no se requiere inicialización porque está diciendo que u puede apuntar a cualquier cosa (es decir, no es constante), pero la cosa a la que apunta no puede cambiar.

Ahora viene la parte confusa. Podría pensar que hacer el puntero inalterable en si mismo, es decir, impedir cualquier cambio en la dirección que contiene u, es tan simple como mover la palabra const al otro lado de la palabra int:

int const* v;

y pensar que esto debería leerse «v es un puntero constante a un entero». Sin embargo, la forma de leerlo es «v es un puntero ordinario a un entero que es constante». Es decir, la palabra const se refiere de nuevo al entero y el efecto es el mismo que en la definición previa. El hecho de que estas definiciones sean equivalentes es confuso, para evitar esta confusión por parte del lector del código, debería ceñirse a la primera forma.