Computación II, Clase 2: Apuntadores

 

Esquema de Un Computador

 

 

 La Memoria del Computador

Características de los Apuntadores

Introducción

Al ejecutarse un programa, las variables se almacenan en memoria, cada una en su propia y única dirección o localidad. Las variables en general contienen un valor odato. Por ejemplo cuando se declara:

int count = 5;

El valor "5" es almacenado en memoria y puede ser accedido usando la variable “count”. 

Un apuntador es un tipo especial de variable que en lugar de contener un valor o dato, contiene una dirección de memoria. Así como los datos pueden modificarse cuando se trabaja con una variable normal, el valor de la dirección almacenada en un apuntador también puede modificarse. Usualmente, la dirección almacenada en el apuntador es la dirección correspondiente a alguna otra variable del programa.

int *ptr;
ptr = &count
/* Guarda dirección de count en ptr */
    
/* el operador unario & retorna la dirección de la  variable */

Para tomar el valor o contenido que es almacenado en la localidad de memoriam enelapuntador, es necesario “de referenciar” al apundator. Esto se hace usando el operador unario “*”.

int total;
total = *ptr;
    /
* The value in the address stored in ptr is assigned to total */

La mejor manera de aprender apuntadores es con la práctica y los ejemplos. Los apuntadores son un tópico difícil. No se preocupen si el panorama no esta completamente claro todavía.

Ejemplo de Declaración e Inicialización

int main()
{
    int j;
    int k;
    int l;
    int *pt1;    
/* Declares an integer pointer */
    int *pt2;    
/* Declares an integer pointer */
    float values[100];
    float results[100];
    float *pt3;    
/* Declares a float pointer */
    float *pt4;    
/* Declares a float pointer */

    j = 1;
    k = 2;
    pt1 = &j;    
/* pt1 contains the address of the variable j */
    pt2 = &k;    
/* pt2 contains the address of variable k */
    pt3 = values;
        
/* pt3 contains the address of the first element of values */
    pt3 = &values[0];
        
/* This is the equivalent of the above statement */

    return 0;
}

Dereferenciacion de Apuntadores y Asignación de valores

La dereferenciacion permite la manipulación de los datos contenidos en la dirección de memoria guardada en el apuntador. El apuntador guarda una dirección de memoria. Al de referenciar un apuntador, podemos modificar los datos o valores contenidos en esa dirección de memoria. El operadorunario “*”, es utilizado para de referenciar a los apuntadores.

*pt1 =*pt1 + 2;

Esta instrucción suma dos al valor apuntado por pt1. Es decir, la instrucción suma dos a; contenido de la dirección de memoria almacenada por pt1. Entonces, a partir del programa principal, pt1 contiene  la dirección de j. La variable "j" fue inicializada con 1. El efecto de la instrucción mostrada arriba es sumar 2 a j.

El contenido de la dirección almacenada en un apuntador, puede ser asignado a otro apuntador o a otra variable

*pt2 = *pt1;    
    
/* assigns the contents of the memory pointed to by pt1 */
    
/* to the contents of the memory pointer to by pt2; */
k = *pt2;
    
/* assigns the contents of the address pointer to by pt2 to k. */

Aritmética de Apuntadores

 Parte del poder de los apuntadores proviene de la habilidad de hacer aritmética en los apuntadores mismos. Los apuntadores pueden ser incrementados, decrementados y manipulados utilizando expresiones aritméticas. Consideremos el apuntador "pt3" y el arreglo de float "values" declarados en el programa principal mostrado anteriormente:

pt3 = &values[0];
    
/* The address of the first element of "values" is stored in pt3*/
pt3++;
    
/* pt3 now contains the address of the second element of values */
*pt3 = 3.1415927;
    
/* The second element of values now has pie (actually pi)*/
pt3 += 25;
    
/* pt3 now points to the 27th element of values */
*pt3 = 2.22222;
    
/ The 27th element of values is now 2.22222 */

pt3 = values;
    
/*pt3 points to the start of values, now */

for (ii = 0; ii < 100; ii++)
{
     *pt3++ = 37.0;    
/* This sets the entire array to 37.0 */
}

pt3 = &values[0];
    
/* pt3 contains the address of the first element of values */
pt4 = &results[0];
    
/* pt4 contains the address of the first element of results */

for (ii=0; ii < 100; ii++)
{
    *pt4 = *pt3;
        
/* The contents of the address contained in pt3 are assigned to
        the contents of the address contained in pt4 */
     pt4++;
     pt3++;
}

 

Pasaje de Parámetros

Por valor: Los valores que se pasan se copian a los parámetros de la función, si el valor de un parámetro se modifica dentro de la función, no se altera su valor en el programa que lo llama.

Por Referencia: Permiten modificar dentro de la función el valor actual de la variable que fue pasada como parámetro. Es decir, el valor de la variable si se altera en el programa que llama.


Podemos distinguir entre parámetros formales y parámetros reales
Parámetros Formales: Aquellos que van en la definición de la función o un prototipo. Son como variables locales a la función que sirven de comunicación con el exterior.
Parámetros Reales: Se colocan en la invocación de la función, pueden ser expresiones o variables del mismo tipo del parámetro formal correspondiente. Deben colocarse en la misma posición del parámetro formal correspondiente, respetando el número tipo y posición de los parámetros formales.

Ejemplo función Swap

void Swap(int x, int y) {

int temp ;
temp = x;
x = y;
y = temp;

}


Con la invocacion, Swap(a,b) ? no tendria ningun efecto, pues los parametros se han pasado por valor. Es decir, no se afectan los valores de a y b.

Debe hacerse pasando los parametros por referencia

void Swap(int *apx, int *apy)
{

int temp ;
temp = *apx;
*apx = *apy;
*apyy = temp ;

}

main()
{

int a = 20, b = 100;
Swap(&a, &b);
// Los valores de a y b se intercambian, a = 100, b = 20

}