23
APUNTADORES INTRODUCCION Objetivos Adquirir destrezas sobre el uso de punteros tanto en C como en C++. Comprender la relación existente entre apuntadores y matrices. Repasar los conceptos teóricos vistos a lo largo de la materia Indice 1. ¿Qué son los apuntadores? 2. Referenciando apuntadores. 3. Deseferenciando un apuntador. 4. Usos de apuntadores. 4.1. Funciones y apuntadores. 4.2. Arreglos y apuntadores. 4.2.1. Aritmética de punteros. 4.2.2. Apuntadores y arreglos multidimensionales. 4.2.3. Accediendo a los elementos de una matriz. 4.3. Apuntadores a apuntadores. Contenido 1. Que son los apuntadores Un apuntador es una variable que almacena una dirección de memoria. Lo primero que se debe hacer al trabajar con apuntadores es declararlos, la forma como se declara un apuntador se muestra a continuación: Donde 1 : Tipo: Tipo de dato al cual se desea apuntar, puede ser un tipo de dato simple (char, int, etc) o un tipo de dato complejo como una estructura o una clase. Modificadores del tipo: Puede contener cualquier combinación de los modificadores de tipo const, volatile y restrict. Nombre: Nombre del apuntador. Valor inicial: Valor inicial del apuntador. Por ejemplo, supóngase que se declaró un puntero a una variable la cual tiene el valor de 5 tal y como se muestra a continuación: 1 Las cosas que se encuentran entre corchetes son opcionales. tipo *[modificadores_del_tipo] nombre [=valor inicial]; int theVariable = 5; int *pPointer = &theVariable;

APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Embed Size (px)

Citation preview

Page 1: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

APUNTADORES INTRODUCCION

Objetivos

Adquirir destrezas sobre el uso de punteros tanto en C como en C++.

Comprender la relación existente entre apuntadores y matrices.

Repasar los conceptos teóricos vistos a lo largo de la materia

Indice 1. ¿Qué son los apuntadores? 2. Referenciando apuntadores. 3. Deseferenciando un apuntador. 4. Usos de apuntadores.

4.1. Funciones y apuntadores. 4.2. Arreglos y apuntadores.

4.2.1. Aritmética de punteros. 4.2.2. Apuntadores y arreglos multidimensionales. 4.2.3. Accediendo a los elementos de una matriz.

4.3. Apuntadores a apuntadores. Contenido 1. Que son los apuntadores Un apuntador es una variable que almacena una dirección de memoria. Lo primero que se debe hacer al trabajar con apuntadores es declararlos, la forma como se declara un apuntador se muestra a continuación: Donde1:

Tipo: Tipo de dato al cual se desea apuntar, puede ser un tipo de dato simple (char, int, etc) o un tipo de dato complejo como una estructura o una clase.

Modificadores del tipo: Puede contener cualquier combinación de los modificadores de tipo const, volatile y restrict.

Nombre: Nombre del apuntador.

Valor inicial: Valor inicial del apuntador. Por ejemplo, supóngase que se declaró un puntero a una variable la cual tiene el valor de 5 tal y como se muestra a continuación:

1 Las cosas que se encuentran entre corchetes son opcionales.

tipo *[modificadores_del_tipo] nombre [=valor inicial];

int theVariable = 5;

int *pPointer = &theVariable;

Page 2: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

En la siguiente figura se muestra el efecto en memoria de la declaración anterior:

Como se puede apreciar el valor almacenado en el apuntador es la dirección de memoria de la variable a la cual está apuntando. Esto fue posible gracias al operador dirección (&). Con base en la figura anterior se construyó la siguiente tabla para clarificar su uso:

Significado Valor

theVariable Contenido de theVariable 5

&theVariable Direccion de theVariable 101

pPointer Contenido del apuntador pPointer 101

&pPointer Direccion del apuntador pPointer 106

Como se puede notar de la tabla anterior el valor obtenido con el operador & es la dirección en la cual se encuentra la variable en cuestión. Como una variable puede ocupar más de 1 byte, el valor resultante es el byte asociado a la dirección base de la variable. Ahora bien, con el apuntador es posible acceder a cualquier lugar de memoria y modificar su valor. Para ello se tiene que referenciar y desreferenciar el apuntador. Esto se describe a continuación: 2. Referenciando apuntadores Consiste en asociar el apuntador a una dirección específica, para esto se suele usar el operador & para obtener la dirección de la variable en cuestión. A continuación se muestra la forma como normalmente se hace esto: También es posible referenciar un apuntador pasándole el valor que se tiene en otro apuntador. Note que no se hizo uso del operador & en este caso:

apuntador = &variable;

apuntador1 = apuntador2;

Page 3: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Todo apuntador debe inicializarse antes de usarse. Si esto no se hace, cuando intente usarlo para hacer alguna operación en memoria el programa sacara un error. Un puntero que no ha sido inicializado se conoce como Wild pointer. En la siguiente figura se ilustra un poco mejor lo anterior:

int i,j;

int *p; //Apuntador a un entero

Hasta el momento solo se ha declarado el apuntador pero no se ha referenciado, en la siguiente figura se muestra el efecto de referenciar el apuntador:

p = &i;

Es posible que varios punteros estén apuntando a un mismo lugar de memoria:

int i;

int *p,*q,*r;

p = &i;

q = &i;

r = p;

Page 4: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

3. Deseferenciando un apuntador Para poder acceder al lugar de memoria que está siendo apuntado por el puntero y realizar operaciones de lectura y escritura sobre este el puntero se debe desreferenciar. Para ello se hace uso del operador desreferencia (*). El valor del lugar de memoria apuntado se obtiene de la siguiente manera: Ahora si lo que se desea hacer es escribir en el lugar de memoria apuntado se hace lo siguiente: La siguiente figura muestra el resultado de desreferenciar un apuntador:

*p = 5;

Como se puede notar de la figura anterior, es posible modificar el valor de i desde el apuntador. Vale resaltar que todo apuntador antes de ser desreferenciado debió haber sido previamente inicializado con una dirección valida. 4. Usos de los apuntadores Los apuntadores se usan principalmente para 3 cosas:

Crear estructuras de datos dinámicas.

Manejar parámetros variables pasados a funciones.

Acceder de a los diferentes elementos de arreglos o estructuras. A continuación se trata con más detalle cada una de estas aplicaciones. 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados a funciones, por referencia y por valor. Cuando se realiza un llamado por valor; se trabaja sobre una copia de la variable pasada como argumento y por lo tanto la variable original (la que se pasó como argumento) no se modifica. Por otro lado, cuando se realiza una llamada por referencia al estar accediendo al lugar de memoria en el que se encuentra la variable pasada como argumento es posible modificar el valor original de la variable pasada como argumento.

variable = *apuntador;

*apuntador = valor;

Page 5: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

El paso de funciones por referencia es de extrema utilidad cuando los argumentos que se están pasando a la función son pesados ya que esto evita que se tengan que hacer copias de dichos argumentos que en el peor de los casos pueden ocasionar que el programa colapse por llenar stack. También, mediante el uso de apuntadores, es posible superar la restricción que se tiene en la cual una función no puede retornar más de un elemento; así, por medio de referencias es posible retornar un array por ejemplo. Para indicar que una función será pasada por referencia, se emplean apuntadores en la cabecera de la función, esto porque lo que se pasa como argumento es la dirección de memoria. Por ejemplo: Para aterrizar un poco más lo anterior, supongamos esta función: Como se pueden notar en la definición de la función anterior, en este caso ambos argumentos son pasados por referencia. Ahora en lo que respecta a la invocación si lo que se pasa es como parámetro es una variable como tal se debe hacer uso del operador & para obtener la dirección de dicha variable y así inicializar el apuntador que funciona como argumento. Por otro lado si lo que se está pasando es un apuntador a una variable, no es necesario usar el operador & ya que el valor almacenado en este será una dirección de memoria. La siguiente tabla ilustra esto:

Caso Invocacion Observaciones

Se está pasando una variable a una función que se llama por referencia

int x = 5, y = 10;

swap(&x,&y); Es necesario usar el operador & para obtener la dirección de memoria de las variables y así poder inicializar lo apuntadores que funcionan como argumentos.

Se está pasando apuntador a una función que se llama por referencia

int x = 5, y = 10;

int *px = &x, *py;

py = &y;

swap(px,py);

Como lo que se pasan son apuntadores previamente inicializados, estos ya tienen la dirección de memoria de la variable que será pasada como argumento de la función, por lo tanto no es necesario usar el operador &.

tipo_retorno f(tipo_1 *pName_1,tipo_2 *pName_2,...,tipo_N *pName_N)

void swap(int *px, int *py) {

int temp;

cout << "Swap. Before swap, *px: " << *px <<

" *py: " << *py << endl;

temp = *px;

*px = *py;

*py = temp;

cout << "Swap. After swap, *px: " << *px <<

" *py: " << *py << endl;

}

Page 6: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

¿Qué sucede si lo que se pasa como argumento es lo resaltado? Codifique y compile el siguiente código:

int x = 5, y = 10;

int *px = &x, *py;

py = &y;

swap(&px,&py);

// Demuestra el uso de funciones por referencia

#include <sdtio.h>

void swap(int *x, int *y);

void swapv(int x, int y);

int main() {

int x = 5, y = 10;

printf("---------------------------------------------------\n");

printf("Llamada por valor \n");

printf("Main. Antes del swap; x: %d, y: %d \n");

swapv(x,y);

printf("Main. Despues del swap; x: %d, y: %d \n");

printf("---------------------------------------------------\n");

printf("Llamada por referencia \n");

printf("Main. Antes del swap; x: %d, y: %d \n");

swapr(&x,&y);

printf("Main. Despues del swap; x: %d, y: %d \n");

printf("---------------------------------------------------\n");

return 0;

}

void swapr(int *px, int *py) {

int temp;

printf("Swapr. Antes del swap; *px: %d, *py: %d\n",*px,*py);

temp = *px;

*px = *py;

*py = temp;

printf("Swapr. Despues del swap; *px: %d, *py: %d\n",*px,*py);

}

void swapv(int x, int y) {

int temp;

printf("Swapv. Antes del swap; x: %d, y: %d\n",x,y);

temp = x;

x = y;

y = temp;

printf("Swapv. Despues del swap; x: %d, y: %d\n",x,y);

}

Page 7: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Preguntas:

¿Cuál es la salida del código anteriormente mostrado y por qué?

El siguiente fragmento de código corresponde a una funcion la cual permite calcular el producto escalar de dos vectores del mismo tamaño:

Una función también puede retornar un apuntador cuando es invocada, para hacer esto, en la definición y declaración de la función se debe indicar que la función retornara un apuntador lo cual se hace precediendo el nombre de la función por un asterisco. A continuación se muestra la forma que debe llevar la función para este caso: Observe el siguiente fragmento de código, el cual consiste en la definición de la función mayor:

Note que lo realimente importante es que se declaró un apuntador a un tipo de dato específico, se inicializo y luego se retornó este, en general en la definición de la función se sigue la siguiente plantilla:

// This function calculates the scalar product of two arrays.

// Arguments: Two arrays of double, and their length.

// The two arrays need not be distinct.

double scalar_product( const double * restrict p1,

const double * restrict p2,

int n )

{

double result = 0.0;

for ( int i = 0; i < n; ++i )

result += p1[i] * p2[i];

return result;

}

int *mayor(int *a,int n) {

int i;

int *m = a;

a++;

for (i = 1; i < n; ++i )

if(*m < *a) {

m = a;

a++;

}

return m;

}

tipo_retorno *f(parametros...)

tipo *funcion(tipo *arg1,...) {

tipo *ptr; // Declaracion del apuntador

ptr = &arg; // Inicializacion del apuntador

/** Operaciones **/

...

return ptr; // Retorno del apuntador

}

Page 8: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Preguntas:

¿Qué es lo que hace la función anteriormente definida?

El parámetro a es un vector, ¿Cuál es la otra forma alternativa de declarar la cabecera para la función?

¿Qué es que se está haciendo en la primera línea resaltada?, ¿Con que otra instrucción puedo hacer lo mismo?

¿Qué es lo que hace la segunda línea resaltada?

¿Qué valor tendrá m en la tercera línea resaltada?

En lo que respecta a la declaración de la función (prototipo de la funcion), esta puede ser hecha de la siguiente forma: O también puede ser de la siguiente forma, sin colocar los nombres de las variables que sirven como argumentos: Recuerde lo importante en la declaración de la función es indicarle al compilador como van a usarse los parámetros. Ahora lo que resta es probar la función, para ello esta debe ser invocada ya sea dentro de la función main o dentro de otra función. Evalúe la función anteriormente creada. Para ello, codifique el siguiente código:

int *mayor(int *a,int n);

int *mayor(int *,int);

#include <stdio.h>

int *mayor(int *a,int n);

int main() {

int a[6] = {1,2,5,9,-1,3};

int *p;

p = mayor(a,5);

printf("El elemento mayor del vector es: %d\n",*p);

return 0;

}

int *mayor(int *a,int n) {

int i;

int *m = a;

a++;

for (i = 1; i < n; ++i )

if(*m < *a) {

m = a;

a++;

}

return m;

}

Page 9: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Note algo realmente importante, cuando se invocó la función se debió declarar previamente un apuntador, el cual va a ser empleado para almacenar el valor retornado por la función. 4.2 Arreglos y apuntadores 4.2.1 Aritmética de punteros Como los apuntadores son variables es posible realizar operaciones matemáticas sobre ellos, sin embargo debido a que lo almacenado en estos son direcciones de memoria no todas las operaciones convencionales que se podrían hacer sobre una variable normal son posibles. Las operaciones validas son:

Añadir o sustraer un entero de un apuntador. Esto hace que el puntero apunte a otro lugar de memoria diferente al que inicialmente estaba apuntando esto debido a la modificación de lo que se encuentra almacenado en este.

Sustraer un apuntador de otro: Cuando se realiza esta operación, los dos apuntadores deben ser del mismo tipo.

Comparar dos apuntadores. La comparación es comúnmente empleada para comparar cualquier puntero con el puntero a NULL usando los operadores de igualdad (== o !=).

Las tres operaciones anteriormente descritas son generalmente útiles para apuntadores que se refieren a los elementos de un array. Recordemos que un array consiste de un conjunto de variables del mismo tipo las cuales pueden ser accedidas bajo un mismo nombre. Cuando se declara un array lo que sucede en memoria es que se reservan un conjunto de posiciones contiguas en memoria tal y como se muestra en la siguiente figura:

Page 10: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Para ilustrar lo anterior suponga lo que tiene dos apuntadores, p1 y p2 los cuales están apuntando a los elementos de un array a:

Si p1 apunta al elemento i del array (a[i]), y n es un entero, entonces la expresión p2 = p1 + n hace que p2 apunta al elemento a[i+n]. (Se asume que i+n está dentro del índice del array).

La resta p2 – p1 da el número de elementos del array entre los dos apuntadores.

La comparación p1 < p2 es cierta si el elemento referenciado por p2 tiene un índice más grande que el referenciado por p1, de otro lado la comparación es falsa.

Lo anterior muestra que existe una relación entre la forma de escribir un array con subíndices y escribirlo con apuntadores aritmética de apuntadores, esto implica que:

El nombre de un arreglo es realmente un apuntador al primer elemento en el array, asi si a es un arreglo adimensional entonces la dirección del primer elemento del array es &a[0] o simplemente a.

La dirección del elemento i del array puede ser expresada como &a[i] o como a + i, por lo tanto existen dos manera de escribir la dirección de cualquier elemento del array.

a[i] o *(a+i) representan el contenido que hay en la dirección en cuestión.

El número de bytes de memoria asociados con cada elemento del array dependerá del tipo de dato empleado en la declaración (1 byte para dados tipo char o 4 para datos tipo doublé por ejemplo). La siguiente figura clarifica lo anterior:

Es posible acceder a cada uno de los elementos del arreglo por medio del índice o de manera alternativa usando apuntadores y es allí donde entra en juego la aritmética de punteros ya que por medio de las operaciones de adición y sustracción nos podemos mover a las diferentes posiciones del array para luego poder acceder a sus elementos. Para entender más esto suponga que tiene la siguiente porción de código:

Page 11: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Como se puede notar del código anteriormente mostrado, el acceso al array fue haciendo uso de subíndices, a continuación se muestra la versión alternativa haciendo uso de apuntadores: Pregunta: ¿Con que valores queda el vector a tras la ejecución del código anteriormente mostrado? El resultado de ejecutar los dos códigos anteriormente mostrados es el mismo. Observe dos cosas:

Para barrer el array se modificó el valor almacenado en el apuntador.

Para acceder a un elemento del array (ya sea para leer o para escribir) se desreferencio el apuntador con el operador asterisco (*).

Dado el siguiente código fuente:

int a[6]={1,0,4,7,8,10};

int i,suma = 0;

a[0]=2;

a[3]=10;

for(i = 1;i<6;i++) {

if(i%2==0) {

a[i] = -a[i];

}

else {

a[i]=a[i]+1;

}

}

int a[6]={1,0,4,7,8,10};

int *ptr; // Declaracion del apuntador

ptr = &a[0]; // Inicializacion del apuntador. (ptr = a)

*ptr = 2; // a[0] = 2

ptr = &a[3]; // Ahora ptr esta apuntando al elemento a[3]

*ptr=10; //a[3] = 10

ptr = &a[1]; // Ahora ptr esta apuntando al elemento a[1]

for(i = 1;i < 6;i++) {

if(i%2==0) {

*ptr = -(*ptr);

}

else {

*ptr = *ptr + 1;

}

ptr++; //Cambio del valor del apuntador para barrer

// el arreglo

}

Page 12: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

¿Qué es lo que hacen las funciones anteriormente mostradas?

Realice un programa en el cual pruebe las funciones anteriormente mostradas. 4.2.2 Apuntadores y arreglos multidimensionales Así como en el caso de los arreglos de una dimensión, es posible representar los arreglos multidimensionales con una notación de punteros equivalente. En el caso de las matrices de dos dimensiones, cuando estas se almacenan en memoria, la forma como la memoria se llena es fila por fila, es decir si se tiene una matriz de n filas por m columnas las primeras n posiciones en memoria corresponden a los n elementos de la primera fila, las n posiciones siguientes corresponden a los n elementos de la siguiente fila y así sucesivamente hasta que todas las filas son ocupadas (n*m posiciones de memoria). La siguiente figura muestra esto:

// The swapf( ) function exchanges the values of two float variables.

// Arguments: Two pointers to float.

inline void swapf( float *p1, float *p2 );

{

float tmp = *p1; *p1 = *p2; *p2 = tmp; // Swap *p1 and *p2.

}

// The function selection_sortf( ) uses the selection-sort

// algorithm to sort an array of float elements.

// Arguments: An array of float, and its length.

void selection_sortf( float a[ ], int n ) // Sort an array a of n float

elements.

{

if ( n <= 1 ) return; // Nothing to sort.

float *last = a + n-1, // A pointer to the last element.

*p, // A pointer to a selected element.

*minPtr; // A pointer to the current minimum.

for ( ; a < last; ++a ) // Walk the pointer a through the array.

{

minPtr = a; // Find the smallest element

for ( p = a+1; p <= last; ++p ) // between a and the end of the array.

if ( *p < *minPtr )

minPtr = p;

swapf( a, minPtr ); // Swap the smallest element

} // with the element at a.

}

Page 13: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Ahora bien, un arreglo de dos dimensiones puede ser tratado como un arreglo de una dimensión cuyos elementos son arreglos de una dimensión (las filas) tal y como lo sugiere la siguiente figura:

Lo anterior hace posible que se pueda definir un arreglo de dos dimensiones como un apuntador a un grupo de arreglos de una dimensión, de modo que una declaración de un arreglo bidimensional puede ser hecha de la siguiente manera:

T *(ptVar)[n];

Page 14: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Donde T está asociado al tipo de dato (el cual puede ser simple o compuesto) y n es el número de filas del array bidimensional. La expresión anterior puede ser por lo tanto una alternativa a la declaración típica de matrices por ejemplo para el caso de una matriz de n filas por n columnas como la siguiente: La expresión anterior se puede generalizar a arreglos de más elementos tal de modo que para una matriz de dimensión N: La expresión alternativa estará dada por: Donde T se refiere al tipo de dato y las expresiones val_1, val_2, …, val_N se refieren al número máximo de elementos asociados con cada uno de los N subíndices del array. Otra cosa importante es la presencia del paréntesis, este es necesario ya que si no está, no nos estaríamos refiriendo a un apuntador a un grupo de arrays sino a un array de apuntadores, esto porque los [] tienen mayor precedencia que el *. Así según lo anterior: Ejemplo 1: Se desea crear un array de bidimensional de 10 filas por 20 columnas llamado x esto puede ser hecho, así: O así: El efecto se muestra en la siguiente figura:

T mat[n][m];

T *(ptVar)[val_2][val_3]...[val_N];

T mat[val1]...[val_N];

int (*pz)[2]; // Crea un apuntador a un array de 2 enteros.

int *pax[2]; // Crea un array de dos punteros a enteros.

int (*x)[20]; // Apuntador a un grupo de 20 enteros contiguos de

// un array unidimensional

int x[10][20];

Page 15: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Donde, x apunta al primer array de 20 elementos, el cual es la primera fila (fila 0), del array original. De manera similar, (x + 1) apunta a los segundos 20 elementos del array (fila 1 del array original) y así sucesivamente hasta la ultima fila. Ejemplo 2: Considere una matriz de tres dimensiones con la siguiente declaración: La declaración alternativa usando apuntadores será: En la declaración anterior, se definió a t como un apuntador a un grupo de 20x30 elementos contiguos de una matriz bidimensional. Por lo tanto según lo anterior, t apuntara a los primeros 20x30 elementos, t +1 apuntara a los segundos 20x30 elementos y así sucesivamente. 4.2.3 Accediendo a los elementos de la matriz Para acceder a un elemento particular dentro de un array particular se emplea el operador indirección (*). A continuación se muestra como: Ejemplo 3: Supongase que se tiene un array entero de 10x20 y se desea acceder al elemento perteneciente a la fila 2 y la columna 5 (x[2][5]) . La forma de acceso es la mostrada a continuación:

float t[10][20][30];

float (*t)[20][30];

*(*(x+2)+5);

Page 16: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Para acceder a dicho lugar de memoria es necesario tener en cuenta una serie de cosas:

x+2: Puntero al vector correspondiente a la fila 2.

*(x+2): Apuntador al primer elemento de la fila 2.

*(x+2)+5: Apuntador al elemento 5 en la fila 2.

*(*(x+2)+5): Elemento de la columna 5 y la fila 2, propiamente x[2][5]. Codifique el siguiente código:

/* zippo2.c -- zippo infovia a pointer variable */

#include <stdio.h>

int main(void)

{

int zippo[4][2] = { {2,4} , {6,8} , {1,3} , {5, 7} };

int (*pz)[2];

pz = zippo;

printf(" pz = %p, pz + 1 = %p\n",

pz, pz + 1);

printf("pz[0] = %p, pz[0] + 1 = %p\n",

pz[0], pz[0] + 1);

printf(" *pz = %p, *pz + 1 = %p\n",

*pz, *pz + 1);

printf("pz[0][0] = %d\n", pz[0][0]);

printf(" *pz[0] = %d\n", *pz[0]);

printf(" **pz = %d\n", **pz);

printf(" pz[2][1] = %d\n", pz[2][1]);

printf("*(*(pz+2) + 1) = %d\n", *(*(pz+2) + 1));

return 0;

}

Page 17: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Preguntas:

¿Cuál es la salida del programa anteriormente mostrado y por qué? 4.2.4 Arreglos de apuntadores Un arreglo de apuntadores es un array cuyos elementos son apuntadores a algún tipo de dato. Estos, constituyen una forma alternativa de expresar un arreglo multidimensional. Por ejemplo un array de dos dimensiones: Puede ser reescrito como un array de apuntadores de la siguiente manera: Luego, generalizando lo anterior para arreglos de N dimensiones tenemos que: La forma alternativa será: Aquí T se refiere al tipo de dato y las expresiones val_1, val_2, …, val_N se refieren al número máximo de elementos asociados con cada uno de los N subíndices del array. Note que a diferencia del caso anterior ya no se emplean paréntesis en este tipo de declaración por lo que el array contendrá apuntadores al tipo específico definido en la declaración. Ejemplo 1: Supóngase que se tiene una matriz bidimensional x de 10 filas por 20 columnas. Esta definida como un vector de apuntadores sera: Aquí, x[0] apuntara al principio de la primera fila, x[1] al principio de la segunda, observe que a diferencia del caso anterior no fue necesario declarar el número de elementos de cada columna de manera explícita. La siguiente figura muestra el efecto de la anterior declaración con más detalle:

T mat[val_1][val_2];

T *ptVar[val_1];

T *(ptVar)[val_2][val_3]...[val_N];

T *(ptVar)[val_1][val_2]...[val_N-1];

int *x[10];

Page 18: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Para acceder a un elemento individual del arreglo, tal como x[2][5] de la siguiente manera: Donde:

x[2]: Es un apuntador al primer elemento de la fila 2.

x[2] + 5: Es un apuntador al elemento 5 dentro de la fila 2.

*(x[2]+5): Se refiere al contenido del elemento de la fila 2 y la columna 5, es decir x[2][5]. Ejemplo 2: Suponga que se tiene un array tridimensional de números de punto flotante de dimensiones 10x20x30. La forma de expresar este array como un array de apuntadores bidimensional es: Lo cual genera un array de 200 apuntadores cada uno de los cuales esta apuntando a un vector unidimensional. Ahora bien, si se desea acceder a un elemento individual tal como t[2][3][5], la forma de accederlo es:

int *(x[2]+5);

float *t[10][20];

*(t[2][3]+5);

Page 19: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Los arreglos de apuntadores ofrecen a menudo un método conveniente para almacenar cadenas de caracteres. En esta situación, cada elemento del array es un apuntador tipo carácter que indica el principio de una cadena de caracteres separada, por lo tanto un array de n elementos puede apuntar a diferentes cadenas de caracteres, de tal manera que cada cadena individual puede ser referenciada por su correspondiente apuntador. La siguiente figura muestra este hecho:

La declaración en C asociada para el caso será: Ahora si quisiera a la segunda frase para imprimirla entonces la instrucción seria: Tambien es posible pasar apuntadores a funciones pero eso no lo vamos a tratar en este caso. 4.3 Apuntadores a apuntadores Es posible poner apuntar un apuntador a un apuntador, lo cual se indica con la cantidad de asteriscos colocados en la declaración del apuntador, así la declaración realizada en las siguientes líneas de código: Tiene el efecto mostrado en la siguiente figura:

char *myStrPtr[99] = {“If anything can go wrong, it will”,

“Nothing is foolproof”,

“Every solution breeds new problems.”};

cout << myStrPtr[1] << endl;

char ch; /*Un caracter*/

char *pch; /*Un apuntado a un dato tipo caracter*/

char **pch; /*Un apuntador a un apuntador a un caracter*/

Page 20: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Cuando se inicializa un apuntador a un apuntador a este se le debe pasar la dirección de memoria del apuntador al que está siendo inicializado, de modo que para obtener el efecto mostrado en la siguiente figura:

Es necesario llevar a cabo las siguientes instrucciones: La siguiente tabla muestra una lista de equivalencias entre los valores almacenados en las variables anteriormente creadas:

Ítem Equivalencia en código

Lugar de memoria accedido ( variable ch) ch = *pch = **ppch

Direccion de la variable ch (&ch) &ch = pch = *ppch

Direccion de memoria del apuntador (&pch) &pch = ppch

Direccion de memoria del apuntador al apuntador (&ppch) &ppch

La anterior tabla implica que si yo quiero cambiar el valor de ch lo puedo hacer ya modificando la variable como tal o desreferenciando el apuntador que la apunta o desreferenciando el apuntador del apuntador que la apunta, a continuación se muestran las tres equivalencias: ch = „A‟; *pch = „A‟; **ppch = „A‟

Lo que se hizo anteriormente fue llevar directa o indirectamente el valor de la variable ch a A. Ejercicio Dado el siguiente código fuente:

pch = &ch; /*Inicializacion del apuntador*/

ppch = &pch; /*Inicializacion del apuntador al apuntador*/

#include <iostream>

using namespace std;

int main() {

char *materias[3]={"Quimica","Matematicas","Fisica"};

float *notasMateria[3];

float **nota;

float nQuimica[]={2,4,5};

float nMatematicas[4]={3.2,1,2.2,5};

float nFisica[] = {4.5,4.3,3.2,1.5,5};

notasMateria[0]=nQuimica;

notasMateria[1]=&nMatematicas[0];

notasMateria[2]=nFisica;

return 0;

}

Page 21: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Preguntas:

Modifique el código anterior de tal manera que pueda imprimir el valor que hay en cada uno de los elementos del vector de apuntadores y llene la siguiente tabla:

Variable Valor

nQuimica

nFisica

nMatematicas

notasMateria[0]

notasMateria[1]

notasMateria[2]

&notasMateria[0]

&notasMateria[1]

&notasMateria[2]

¿De cuánto es el tamaño reservado por el compilador para una variable tipo float (recuerde el operador sizeof)?

¿Cuál es el efecto que se obtendría al ejecutar cada una de las siguientes instrucciones?, ¿Si alguna de estas genera error explique por qué?

Instrucción Comentario

nFisica[0]=3.0; Lleva al elemento 0 del array nFisica el valor de 3.

*(nMatematicas+2) = 3.5;

*(&nQuimica[2]-1) = 2.2;

*(notasMateria[2]+4)=0;

*(notasMateria+2)=0.5;

*(&notasMateria[1]+2)=0.5;

Dada la siguientes instrucciones cual es la forma equivalente de acceder desde el vector de apuntadores notasMateria:

Instrucción Instruccion

nFisica[0]=3.0; *(notasMateria[0])=3.0;

nMatematicas[3]=0.7;

nQuimica[2]= nQuimica[0]+ nQuimica[1];

nMatematicas[3]=nQuimica[2];

nFisica[0]=(nFisica[1]+nFisica[2])/2;

nMatematicas[2]=4.8;

¿Es valida la siguiente instrucción?

En caso de ser válida ¿qué es lo que hacer?, ¿Cuál es el valor de la variable nota?

nota = &notasMateria[2];

Page 22: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

Supongase que se añade al codigo anteriormente mostrado, las siguientes líneas de codigo, que se hace en cada una de estas, ¿Qué se modifica?

Referencias C in an Nutshell. C++ in a Nutshell. Sam teach yourself C++ in 21 days. Shaum’s outline of programming with C. A introduction to design patterns in C with Qt4. C primer plus. http://docs.google.com/viewer?a=v&pid=sites&srcid=ZGVmYXVsdGRvbWFpbnxjYXJsb3NobWVuZG96YWN8Z3g6MjFkZTI1MWJjYjM1ZWZmOA http://www.virtual.unal.edu.co/cursos/ingenieria/2001839/modulo4/cap_05/leccion_3.htm https://users.cs.jmu.edu/bernstdh/web/common/lectures/ http://computer.howstuffworks.com/c.htm http://pw1.netcom.com/~tjensen/ptr/ch9x.htm http://home.earthlink.net/~momotuk/pointers.pdf http://www.lysator.liu.se/c/c-faq/c-2.html http://www.cs.cf.ac.uk/Dave/C/node12.html#SECTION001210000000000000000 http://www.technoplaza.net/programming/lesson9p2.php http://icesecurity.org/programacion/C/cursoc9.html http://www.csse.monash.edu.au/~dwa/Animations/index.html http://www.u-gakugei.ac.jp/~miyadera/Education/TeachingSystem/Animations/LinkedList/linkedlist.html http://www.macs.hw.ac.uk/~rjp/Coursewww/Cwww/linklist.html http://www.ehow.com/how_2056292_create-linked-list-c.html http://www.codeproject.com/KB/cpp/linked_list.aspx http://cslibrary.stanford.edu/103/ http://www.codeproject.com/KB/cpp/PointerArticle.aspx http://www.enm.bris.ac.uk/staff/pjn/EMAT10920/lesson10a.pdf http://cplus.about.com/od/learning1/ss/pointers2.htm http://www.sethi.org/classes/comp217/lab_notes/lab_10_pointers.html http://www.cs.uregina.ca/Links/class-info/115/10-pointers/ http://cboard.cprogramming.com/c-programming/124384-advanced-pointer-use.html http://computer.howstuffworks.com/c30.htm http://www.technoplaza.net/programming/lesson9p2.php http://www.cs.cf.ac.uk/Dave/C/node12.html http://cplus.about.com/od/learningc/ss/pointers2_8.htm http://cslibrary.stanford.edu/102/PointersAndMemory.pdf http://publications.gbdirect.co.uk/c_book/chapter5/pointers.html

nota = &notasMateria[1];

cout << &notasMateria[1]<<" "<<&notasMateria[2]<<" "<<nota<<endl;

*nota += 2;

cout << &nMatematicas[2] << " " <<*nota << endl;

**nota = 0.7;

Page 23: APUNTADORES INTRODUCCION - Teoría del Aprendizaje de ... · PDF fileApuntadores y arreglos multidimensionales. ... 4.1 Funciones y apuntadores Existen dos maneras de hacer llamados

http://www.math.northwestern.edu/~wphooper/code/c/examples/pointers/ http://idlastro.gsfc.nasa.gov/idl_html_help/Pointer_Examples.html http://augustcouncil.com/~tgibson/tutorial/ptr.html http://cplus.about.com/od/learning1/ss/pointers.htm http://cplus.about.com/od/learningc/ss/pointers_9.htm http://icesecurity.org/programacion/C/cursoc22.html#arriba