La memoria de un computador está constituida por celdas contiguas de forma que, en cada una de ellas, puede almacenarse un byte. Cada una de estas celdas o posiciones de memoria tiene una dirección que se expresa en hexadecimal, mediante el direccionamiento segmentado (una dirección viene dada por dos partes: segmento y desplazamiento dentro de este segmento, por ejemplo 0F4C:E0A4). Las direcciones comienzan por la 0000:0000 y se extienden en función de la memoria disponible. Asimismo cada posición de memoria tiene un contenido, es decir, el dato almacenada en ella.
La ocupación de memoria al almacenar datos es función del tipo de que se trate. Como ya hemos visto un carácter ocupa un byte y un entero ocupa 2 o 4 bytes. En algunos programas puede ser necesario conocer directamente las direcciones de los datos almacenados en la memoria, o saber qué contenido tiene una posición de memoria concreta. Asimismo debe existir alguno método que posibilite el acceso a la misma información desde diferentes partes o módulos del programa.
En C esto se logra mediante los punteros. Un puntero (pointer) es una variable que puede almacenar una dirección de memoria, generalmente la dirección de memoria de otra variable. Por los motivos explicados antes, en declarar un puntero, debe indicarse el tipo de datos al que apunta. Los punteros pueden apuntar a cualquier tipo de datos de C, tanto primitivos como definidos, así como en el tipo void. Para aclarar el concepto de puntero, pasamos a considerar el siguiente fragmento de programa:
int * pPunter; (En pseudocódigo : pPunter: ↑ entero;)
Se declara el puntero pPunter. En la declaración, su identificador debe ir precedido del símbolo asterisco *. Este puntero apunta a variables de tipo int, es decir, podrá almacenar direcciones de memoria de variables de este tipo. Es importante entender que el puntero se llama pPunter, sin el asterisco.
int iVariable = 10;
Se declara una variable entera iVariable a la que se le asigna el valor 10. Se ha reservado, por tanto dos bytes de memoria que contienen este valor.
¿Cuál es la posición de memoria concreta en la que se ha almacenado este valor? Para saberlo, se utiliza el operador dirección &, aplicable a cualquier tipo de variable. De esta forma, &iVariable es la dirección inicial de memoria (primer byte) de la variable iVariable. Dado que es una posición de memoria, podemos asignarla a un puntero:
pPunter = &iVariable
Ahora el puntero pPunter contiene la dirección de memoria inicial de iVariable. Dicho de otra forma, apunta a iVariable.
Para saber el contenido de una posición de memoria, se utiliza el operador *. Este operador sólo es aplicable a punteros. La expresión pPunter significa “contenido de la posición de memoria a la que apunta el puntero pPunter”. Dado que pPunter es un puntero en la variable entera iVariable, el valor de *pPunter será 10, el mismo que la variable iVariable.
¿Qué resultado nos daría la expresión &pPunter? Aunque parezca complicada, la expresión anterior significa “dirección de memoria del contenido de la dirección de memoria a la que apunta pPunter”. Por tanto:
&*pPunter = pPunter