Vous êtes sur la page 1sur 12

INSTITUTO TECNOLÓGICO DE SALINA CRUZ

ACTIVIDAD:

U6-01 Investigación

NOMBRE (S):

Melchor Diaz Adriel Alfonso


Molina Conde Alvaro Miguel
Gilberto Santiago Melchor
Villalobos Moreno Jordy

ASIGNATURA:

Algoritmos y programación

GRADO Y GRUPO:

1B2

CARRERA:
Ingeniería Mecánica

FACILITADOR:
ING. JULISSA ANDREA ALQUISIRIS SIBAJA

SALINA CRUZ, OAX. A <04/05/2019>


UNIDAD 6: APUNTADORES
Los apuntadores en C y C++ son una herramienta muy potente de programación
que suele causar mucha confusión en los estudiantes que la están aprendiendo.
Además, cuando los programadores cometen un error en su utilización, puede ser
muy difícil encontrar el error, por lo cual es importante saber utilizarlos muy bien.
El uso de apuntadores en C y C++ es muy importante debido a que permite hacer
los programas más eficientes y mas flexibles. En este artículo se explica de una
manera sencilla y breve todo lo referente a la utilización de apuntadores tanto en C
como en C++.
Todo lo explicado en este artículo aplica tanto para C como para C++, a menos que
se especifique un lenguaje en particular. En algunos ejemplos de código que son
aplicables a C aparecen instrucciones de entrada y salida de las librerías estándar
de C++
Cuando se declara una variable, el compilador reserva un espacio de memoria para
ella y asocia el nombre de esta a la dirección de memoria desde donde comienzan
los datos de esa variable. Las direcciones de memoria se suelen describir como
números en hexadecimal.
Un apuntador es una variable cuyo valor es la dirección de memoria de otra variable.
Se dice que un apuntador “apunta” a la variable cuyo valor se almacena a partir de
la dirección de memoria que contiene el apuntador. Por ejemplo, si un apuntador p
almacena la dirección de una variable x, se dice que “p apunta a x ”.
6.1 REPRESENTACION DE UN APUNTADOR
Los apuntadores son uno de los tabúes del lenguaje de programación C (otro tabú
es la recursividad aunque ésta no está asociada con ningún lenguaje sino con la
programación).Esta entrada introduce a los conceptos y manipulación de
apuntadores; la principal intención es que los apuntadores dejen de ser un tabú y
pasen a ser parte del repertorio de herramientas del programador, ya que los
apuntadores son, en más de un sentido, la piedra angular del lenguaje de
programación C.

Definición, estructura y representación.La sencillez de los apuntadores se basa


en su definición la cual es bastante fácil de recordar y es, en esencia, casi todo lo
que se tiene que saber respecto a los apuntadores y de ahí la importancia de su
comprensión.

Un apuntador almacena direcciones de memoria. Básicamente hay dos tipos de


apuntadores:

1. Apuntadores a variables.
2. Apuntadores a funciones.
Si el apuntador es a una variable, entonces el apuntador almacena la dirección en
memoria de dicha variable. Si el apuntador es a una función, entonces el apuntador
almacena la dirección en memoria del inicio del código de dicha función. Por ser en
principio más simples, se presentarán primero los apuntadores a variables.

(a) Representación de un apuntador (abstracción).

(b) Representación física (en memoria) de un apuntador.


La declaración de una variable de tipo apuntador tiene la siguiente estructura
general en el lenguaje de programación C:
tipo_de_dato * nombre_del_apuntador;

en donde:

 tipo_de_dato es cualquier tipo de dato válido en C.


 nombre_del_apuntador es un identificador válido en C.
 * es el operador que denota que la variable nombre_del_apuntador es una
variable de tipo apuntador a tipo_de_dato.
Una variable de tipo apuntador debe ser congruente, es decir, sólo puede hacer
referencia (apuntar) a variables de su mismo tipo de datos; así por ejemplo, una
variable de tipo apuntador a int puede hacer referencia a una variable de tipo int,
mientras que una variable de tipo apuntador a float puede hacer referencia a una
variable de tipo floaty así sucesivamente para los demás tipos de datos.

Piedra angular de la piedra angular.La línea 9 muestra la declaración de dos


variables de tipo apuntador a entero: aPtr y bPtr (note que como parte del
identificador para cada una de las variables, se ha utilizado Ptr (Pointer) a forma de
sufijo, esto no es obligatorio ni por sí mismo vuelve a la variable de tipo apuntador,
pero es una buena práctica de programación el hacerlo así, debido a que refuerza,
por auto documentación, que la variable es de tipo apuntador, ya que después de
la declaración, no hay nada particular en la variable que en sí misma denote que es
o no de tipo apuntador). Observe que el operador "*" no se distribuye en las variables
como lo hace el tipo de dato, por lo que por cada variable de tipo apuntador que se
necesite, se deberá escribir dicho operador para especificar que la variable asociada
es de tipo apuntador.

Las líneas 11, 12 y 13 inicializan a la variable a con 40178, y a aPtr y bPtr con
la dirección en memoria de a. El operador "&" obtiene la dirección en memoria del
operando (variable) asociado(a), y se conoce como el operador de dirección.

Una variable de tipo apuntador, al ser una variable cuyo contenido es la dirección
en memoria de otra variable, almacena direcciones de memoria obtenidas por el
operador de dirección (el único valor que puede asignarse directamente a una
variable de tipo apuntador es el 0, denotando así que el apuntador no hace
referencia a nada, es decir, que no apunta a ninguna dirección válida de memoria
en cuyo caso se dice que es un apuntador nulo), y aunque en principio es posible
asignarle a un apuntador un valor específico, esto generará, con toda seguridad una
violación de memoria y el programa será terminado por la mayoría de sistemas
operativos (ningún sistema operativo debería permitir la intromisión en áreas de
memoria que no sean las propias del programa, ya que ésto incurriría en graves
errores de seguridad). Las figuras anteriores (a) y (b) ilustran lo que ocurre en las
líneas 11-13. Las funciones printf de las líneas 15 y 16 contienen el especificador
de formato "%p" (pointer), el cual permite visualizar en la salida estándar direcciones
de memoria. Note cómo la dirección de memoria que se imprime en estas líneas es
la misma, tal y como lo muestra la siguiente figura:

La línea 19 muestra el uso del operador de


desreferencia "*", el cual se utiliza para
acceder al valor de la variable a la que se apunta
o se hace referencia a través del apuntador.

Para variables de tipo apuntador, el operador "*" tiene una dualidad:

1. En la declaración de variables: se utiliza o sirve para denotar que la


variable asociada es de tipo apuntador.
2. En la desreferencia de variables: se utiliza o sirve para acceder al
valor al que hace referencia o apunta el apuntador.
Finalmente, la línea 21 modifica el valor de la variable a a través del
apuntador bptr (recuerde que la variable a está siendo referida (apuntada) por las
variables aPtr y bPtr (líneas 12 y 13 respectivamente)), y del operador de
desreferencia, por lo que el valor a imprimir en la salida estándar para la variable a,
será 2018, tal y como lo muestra la figura anterior.

Antes de continuar, asegúrese de entender en su totalidad el Ejemplo 7.1 y lo que


se ha descrito de él, ya que se insiste en que su comprensión es fundamental para
entender los conceptos descritos en las entradas siguientes.
6.2 PRECEDENCIA DE OPERADORES DE APUNTADORES
Los operadores utilizados para trabajar variables apuntadores son el ( * ) asterisco
llamado operador de dirección, y el ( & ) ampersand, llamado operador de dirección.
* toma su operando como una dirección de memoria y retorna la información
almacenada en ese lugar.
& devuelve la dirección de memoria de su operando.
Veamos un ejemplo llamado en el siguiente listado.
Aplicación práctica del uso de apuntadores
#include <iostream.h>
#include <conio.h>
void main(void)
{
int x, y; Define x, y variables enteras.
int *p, *q; Define p y q variables tipo apuntador.
p = &x; asigna a p la dirección de x. (p apunta a x).
q = &y; asigna a q la dirección de y. (q apunta a y).
*p = 10; almacena en x el valor 10.
*q = *p * 2; almacena en y el valor de x multiplicado por 2 (20).
y = y + *p; a la variable y le suma el valor en x (20+10).
cout<<*p; imprime el contenido de x (10).
cout<<,*q; imprime el contenido de y (30).
getch();
}

Variables automáticas y apuntadores


Las variables automáticas se crean en tiempo de compilación y se destruyen al
terminar la ejecución del módulo donde fueron declaradas. Aunque no es
estrictamente necesario, se pueden manejar las variables automáticas por medio
de apuntadores, veamos un ejemplo.
Implementación de variables automáticas
#include <iostream.h>
#include <conio.h>
void main()
{
int automatica ; // Se declara la variable automatica.
int *apunt ; // Se declara el apuntador apunt, que apuntará a objetos de tipo int.
automatica = 100 ; // Se asigna el valor 100 a la variable automática.
apunt = &automatica ; // Se asigna a apunt la dirección de automatica ó apunt apunta
a
// automatica.
clrscr();
cout << "VALOR=" << automatica << " \n"; // 100
*apunt="200" ; // Se asigna el valor 200 al objeto apuntado- // por apunt.
cout << "VALOR=" << automatica << " \n"; // 200
getch();
}
Las instrucciones del listado anterior se traducen en la siguiente secuencia, donde
los apuntadores se representan con una flecha (para simular que "apuntan hacia" ó
"señalan" un objeto) y los objetos apuntados se representan por un cuadro (para
simular un recipiente).

Un apuntador es una variable que solo puede


contener un valor a la vez, por lo que solo
puede apuntar a un objeto al mismo tiempo.
Por otro lado, una variable cualquiera puede
ser apuntada (referenciada) por varios
apuntadores, ya que su dirección de memoria
puede ser almacenada en distintas variables
a la vez. Al declarar un apuntador, se está
especificando el tipo de variable al que va a
apuntar. Por ejemplo, no podrá declararse un
apuntador a objetos de tipo int y después intentar utilizarlo para apuntar a objetos
de tipo float. Cuando se desee manejar un apuntador a cualquier tipo de objeto, se
puede declarar de tipo void, como en: void *multiusos;.
6.3 LLAMADAS POR REFERENCIA
Como vimos las funciones por lo general reciben parámetros, éstos hasta el
momento fueron pasados a la función mediante el "paso por valor" que consiste en
hacer una copia del argumento, para que la función trabaje con la copia y no con el
argumento original.
Esto significa que, si la función modificara el valor, el original no se alteraría ya que
estamos manejando una copia. Esto resulta bastante útil para asegurarnos de que
la función no modifique nuestros argumentos de manera accidental.
Pero surgen dos problemas:
Podríamos querer modificar el argumento original y no una copia.
Con mucha cantidad de variables (o estructuras como veremos) el paso por valor
(copiando) puede resultar un gasto excesivo de memoria.
Para resolver estos problemas contamos con las referencias y punteros, por el
momento nos ocuparemos de las referencias.
Una referencia a una variable es un "alias" de la variable. Para indicarle a C++ que
estamos hablando de una referencia y no una variable anteponemos al nombre el
caracter ampersand (&).
Por ejemplo una referencia llamada refPresupuesto apuntando a un valor double se
escribiría así:
double &refPresupuesto
Si quisieramos que una función trabaje con la variable original y no con una copia
podríamos indicarle a la función que reciba el parametro como una referencia,
veamos un ejemplo:
//Paso por referencia
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void elevarCuadrado (int &); //prototipo de funcion que recibe una referencia a un int
int main()
{
int x = 0; //Declaracio e inicializacion en 0.
cout << "Ingrese x para elevarlo al cuadrado" << endl;
cin >> x;
cout << "antes de elevarse es " << x <<endl;
elevarCuadrado(x); //Notar que la llamada no es diferente a un paso por valor.
cout << "x despues de elevarse es " << x << endl;//muestra el valor modificado por
la funcion
return 0;
}
void elevarCuadrado (int &y ) //funcion que no devuelve nada (void) y recibe una
referencia a un int en este caso (x)
{
y = y*y; //La funcion no devuelve ningun valor, pero modifica el argumento original
(x)
//ya que estamos trabajando con una referencia.
}
Cuando una función se declara anteponiendo la palabra reservada void le estamos
diciendo a C++ que esa función no devolvera valor alguno.Como se comenta en el
código, en la llamada de la función es importante notar que no hay manera de darse
cuenta si el parametro es pasado por referencia (modificable) o si es por valor (se
le envía una copia a la función).

PASO POR REFERENCIA CONSTANTE


Además de poder modificar el valor, aquí obtenemos la ventaja de no realizar una
copia de la variable en cuestión. Sin embargo, podríamos querer obtener esta
ventaja (de aprovechar memoria), pero no perder la protección de la variable (que
la original no pueda ser modificada por la función). Este problema se resuelve,
declarando en la función una referencia constante, con la palabra reservada const.

Esto haría que se pase el argumento por valor, pero que no se permita la
modificación de la variable original. Si al código anterior le agregasemos la palabra
const en el prototipo y en la declaración, e intentasemos compilarlo generaríamos
un error, ya que el compilador nos avisa que no se puede modificar el valor al que
apunta la referencia, lo cual es muy útil para detectar errores. El código quedaría
así y pueden probarlo:
//Paso por referencia constante.
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void elevarCuadrado (const int &); //prototipo de funcion que recibe una referencia
a un int
int main()
{
int x = 0; //Declaracio e inicializacion en 0.
cout << "Ingrese x para elevarlo al cuadrado" << endl;
cin >> x;
cout << "antes de elevarse es " << x <<endl;
elevarCuadrado(x); //Notar que la llamada no es diferente a un paso por valor.
cout << "x despues de elevarse es " << x << endl;
return 0;
}
void elevarCuadrado (const int &y ) //funcion que no devuelve nada (void) y recibe
una referencia a un int en este caso (x)
{
y = y*y; // Error no se puede modificar ya que es constante.

}
Aviso del compilador:

refConstEj.cpp: In function ‘void elevarCuadrado(const int&)’:


refConstEj.cpp:19: error: assignment of read-only reference ‘y’
Ver como hacer para compilar este programa.
6.4 UTILIZACION DE ARREGLOS
Es muy importante debido a que permite hacer los programas más eficientes y más
flexibles.
Cuando se declara una variable, el compilador reserva un espacio de memoria para
ella y asocia el nombre de esta a la dirección de memoria desde donde comienzan
los datos de esa variable. Las direcciones de memoria
Se suelen describir como números en hexadecimal.
Un apuntador es una variable cuyo valor es la dirección de memoria de otra variable.
Se dice que un
Apuntador “apunta” a la variable cuyo valor se almacena a partir de la dirección de
memoria que contiene el
Apuntador. Por ejemplo, si un apuntador
p
Almacena la dirección de una variable
X
se dice que
p
Apunta a
X

La referenciación es la obtención de la dirección de una variable. En

C++
Esto se hace a través del
Operador ‘&’, aplicado a la variable a la cual se desea saber su dirección. Nótese
que se trata de un operador
Unario. Ejemplo:
Este código imprime un valor del estilo “
0x4fffd34
”. Este valor puede variar durante cada ejecución del
Programa, debido a que el programa puede reservar distintos espacios de memoria
durante cada ejecución.

DECLARACION DE APUNTADORES

Para declarar un apuntador se especifica el tipo de dato al que apunta, el operador


‘*’, y el nombre del
Apuntador. La sintaxis es la siguiente:

<Tipo de dato apuntado> * <Identificador del apuntador>


A continuación se muestran varios ejemplos:

ASIGNACION DE APUNTADORES
Se pueden asignar a un apuntador direcciones de variables a través del operador
de referenciación (‘&’) o direcciones almacenadas en otros apuntadores. Ejemplos:
CONCLUSION
Despuer de haber investigado sobre este tema “apuntadores” muy importantes para
la creación de algoritmos y la programación en sí, plateamos 5 puntos muy
importantes a tomar en cuenta antes de programar que son los siguientes:
 Los apuntadores son una gran ayuda para referenciar variables.
 Su uso es demasiado delicado.
 Un apuntador siempre referenciar direcciones.
 Un doble apuntador es "una referencia de otra referencia".
 Los tipos de datos de apuntador y variable apuntada deben coincidir.
Y con esto damos por terminada la investigación de este tema.

Vous aimerez peut-être aussi