Los punteros
Objetivos del capítulo
Desarrollar aplicaciones que utilicen punteros.
Desarrollar aplicaciones que utilicen la asignación dinámica de memoria.
Definición
Un puntero es una variable destinada a contener una dirección. Como una dirección es un entero, un puntero es una variable de tipo entero.
Ejemplos
1. Puntero sobre un entero
La declaración int* p reserva un entero en memoria, destinado a contener la dirección de una variable de tipo entero.
La escritura int* p (la estrella pegada a int) sugiere que la variable p es del tipo puntero sobre un entero. También podríamos escribir int *p (la estrella pegada a la p), que sugiere que la variable *p es de tipo entero, lo que también es cierto.
-
La declaración int n reserva un entero en memoria.
int main()
{
int* p;
int n;
n = 17;
printf("n = %d\n\n", n);
La siguiente instrucción inserta la dirección de la variable n en p (el operador & devuelve la dirección de n). Se dice que p apunta a n.
p = &n;
printf("p = %p\n\n", p);
El formato %p del printf permite mostrar el entero p en hexadecimal.
Visualización del valor apuntado por p:
printf("*p = %d\n\n", *p);
Incremento del valor apuntado por p, es decir, n:
(*p)++;
printf("n = %d\n\n", n);
return 0;
}
A continuación se muestra el resultado de la ejecución de este programa:
El operador & devuelve la dirección de una variable.
Es posible almacenar esta dirección en una variable...
Punteros: un error clásico
La utilización directa de direcciones de memoria puede ser peligrosa y obliga a prestar atención al programador. El siguiente ejemplo ilustra este peligro.
int main()
{
int* p;
La siguiente instrucción inserta la dirección 0 en el puntero. En general, esta dirección se reserva a los programas del sistema.
p = 0;
La siguiente instrucción intenta insertar el valor 10 en la dirección 0; por lo tanto, eliminar un fragmento de programa del sistema (aquí, Windows):
*p = 10;
return 0;
}
Windows se defiende y muestra una pequeña ventana de información:
Este error se califica como Access Violation.
Asignación dinámica de una tabla
La asignación dinámica de memoria consiste en reservar espacio de memoria para variables a lo largo de la ejecución del programa. Por ejemplo, la asignación dinámica de una tabla puede ser útil si su dimensión no se conoce al inicio del programa.
1. Tabla de una dimensión
Las siguientes declaraciones reservan dos zonas de memoria que pueden contener un entero.
int main()
{
double* tabla;
int i;
La función calloc() reserva en memoria un número de bytes igual al producto de sus argumentos.
tabla = (double*) calloc(3, sizeof(double));
printf("tabla = %p\n\n", tabla);
Aquí: 3 * sizeof(double), es decir, 3 * 8 = 24 bytes; es decir, el espacio correspondiente a tres variables de tipo double.
La función calloc() devuelve una dirección no tipada (void*). El «cast» en double* garantiza una coherencia con la declaración del puntero tabla. La dirección devuelta por calloc() se almacena en tabla, que apunta a la zona de memoria asignada:
Sin embargo, la tabla se utiliza como una tabla normal:
tabla[0] = 5.1;
tabla[1] = 17.3;
tabla[2] = 13.4;
for (i = 0; i < 3; i++)
{ ...
Trabajo práctico: triángulo de Pascal
1. Objetivo
Constituir una tabla que contenga el triángulo de Pascal usando la asignación dinámica de tablas.
2. Tema
La corrección del trabajo práctico: triángulo de Pascal (cf. capítulo Las tablas) propone una solución que utiliza dos tablas de una dimensión. Retomando este programa, se asignan dinámicamente las dos tablas.
3. Triángulo de Pascal: proposición de corrección
Esta solución retoma la solución con dos tablas de una fila. Las tablas se asignan dinámicamente. Las variables l1 y l2 se declaran como punteros:
int main()
{
int* l1;
int* l2;
int* permut;
int fila,col;
int numl;
printf("Indique el número de fila(s) de la tabla: ");
scanf("%d", &numl);
Asignación dinámica de las dos tablas:
l1 = (int*) calloc(numl, sizeof(int));
l2 = (int*) calloc(numl, sizeof(int));
El número de filas del triángulo de Pascal no está limitado a 16.
l1[0] = 1;
printf("%-5d\n", l1[0]);
for (fila = 1; fila < numl; fila++)
{ ...