Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 17

UNIVERSIDAD NACIONAL EXPERIMENTAL POLITÉCNICA

“ANTONIO JOSE DE SUCRE”


VICE-RECTORADO PUERTO ORDAZ
COMPUTACIÓN II - SECCIÓN M2

Punteros

Profesor: Estudiante:

Wilmen Cortez Victor Manuel Henriquez

CI. 26.499.927

Ciudad Guayana, Marzo del 2023


1. ¿Que son punteros?

El C++ nos permite controlar casi todos los aspectos de la ocupación y gestión de
memoria de nuestros programas (sabemos lo que ocupan las variables, podemos trabajar
con direcciones, etc.).

Uno de los conceptos fundamentales en este sentido es el de puntero. Un puntero


es una variable que apunta a la dirección de memoria donde se encuentra otra variable;
almacena la dirección de memoria de un objeto. La clave aquí está en la idea de que un
puntero es una dirección de memoria.

Los punteros se usan ampliamente en C y C++ para tres propósitos principales:


• para asignar nuevos objetos en el montón,
• para pasar funciones a otras funciones
• para iterar sobre elementos en matrices u otras estructuras de datos.

2. Importancia de los punteros

Los punteros crean código eficiente y rápido, proporcionan asignación de memoria


dinámica. Hacen expresiones compactas y concisas; también protegen datos pasados como
parámetros a una función.

Proporcionan la capacidad de pasar estructuras de datos mediante un puntero sin


ocasionar un exceso de código conocido como “overhead”. Es mucho menor al utilizar
punteros a diferencia de la cantidad de “overhead” que podría presentarse al utilizar otros
operadores.

La asignación de memoria dinámica es otro uso potente que mejora la


administración de memoria del sistema ya que la reserva de memoria se realiza en tiempo
de ejecución, es decir cuando el programa se está ejecutando.
Los punteros representan una herramienta poderosa para crear aplicaciones. Un
puntero es importante porque es la forma de asociar una dirección de memoria con un
valor, dado que es la manera en que se realizan operaciones en el C.P.U (algo heredado
de la arquitectura de Von Neumann). Esto permite tener mayor control sobre todas las
variables que utilice un programa, desde liberar memoria hasta construir nuevas variables
(espacios de memoria).

3. ¿Cómo se define y declara un puntero de tipo entero, carácter o un dato estructurado?

Para definir y declarar se escribe el tipo de puntero luego un asterisco seguido del
nombre que le asignaremos a la variable del puntero:

- Entero:
int *puntero
- Carácter:
char *puntero
- Dato estructurado:
Ntipo *puntero

4. ¿Cuáles son las operaciones básicas que se utilizan en punteros?

Existen 3 operaciones básicas de los punteros:

• Declaración (*):

Los punteros se declaran con un asterisco, de esta forma:


tipo * variable
Por ejemplo
int* puntero;

Se dice que la variable Puntero es un puntero a enteros (apunta a un entero)


• Dirección (&):

El valor que puede adquirir un puntero es, por ejemplo, la dirección de una
Variable. El operador “&” devuelve la dirección de una variable:

puntero = &variable

El operador & se utiliza para asignar valores a datos de tipo puntero:


int i;

int *ptr;

...

ptr = &i;

• Asignación (=):

Se puede alterar la variable a la que apunta un puntero. se le puede asignar una


dirección de memoria concreta, la dirección de una variable o el contenido de otro puntero.

- Una dirección de memoria concreta:

int *ptr;

...

ptr = 0x1F3CE00A;

...

ptr = NULL;

- La dirección de una variable del tipo al que apunta el puntero:

char c;

char *ptr;

...

ptr = &c;
- Otro puntero del mismo tipo:

char c;

char *ptr1;

char *ptr2;

ptr1 = &c;

ptr2 = ptr1;

Como todas las variables, los punteros también contienen “basura” cuando se
declaran, por lo que es una buena costumbre inicializarlos con NULL.

5. ¿Cómo sumamos dos números usando punteros?

Para sumar dos números usando punteros se accede con punteros al valor
guardado en las direcciones de ambas variables y se suman:
6. ¿Cómo modificamos en datos de una variable de tipo entero y de tipo carácter de forma
indirecta?

Asignándole la dirección de la variable al puntero, luego se modifica el valor de la


variable desde el puntero accediendo al valor que este contenido en la dirección que apunta
el puntero.

7. ¿Cómo apuntamos a la dirección de un arreglo unidimensional y bidimensional de tipo


entero y de tipo carácter usando punteros? Indique un ejemplo para cada caso.

Arreglo unidimensional de números enteros

Con el arreglo ya declarado y con valores, se declara un puntero que apunte a la


dirección de la primera posición del arreglo.
Posiciones de los valores en el arreglo “arr” 5 2 3

Arreglo bidimensional de números enteros

Con el arreglo ya declarado y con valores, se declara un puntero que apunte a la


dirección de la primera fila y primera columna del arreglo

Posiciones de los valores en el arreglo “arr”

1 4 7
2 5 8
3 6 9
En el caso de arreglo de caracteres se hace el mismo procedimiento, pero la
dirección mostrada no será la típica como con los enteros.

Arreglo unidimensional de caracteres

Posiciones de los valores en el arreglo “arr”

a b c
Arreglo bidimensional de caracteres

Posiciones de los valores en el arreglo “arr”

h j o
c f e
s a d
8. ¿Cómo accedemos a los campos de un registro usando punteros? Indique un ejemplo.

Para acceder a los campos de un registro por medio de un puntero se debe crear un puntero
del mismo tipo que el registro que apunte a la dirección del registro la cual se toma
automáticamente como la dirección del primer campo del registro.

Al momento de ver el valor contenido en la dirección a la que apunta el puntero se


debe escribir entre paréntesis el comando correspondiente y luego fuera del paréntesis el
campo a solicitar
9. Se debe cargar y mostrar un registro usando punteros.
10. ¿Cuál es la diferencia entre punteros y arreglos? Indique un ejemplo.

Un puntero es una variable que ocupará de 4 a 8 bytes dependiendo de la


arquitectura del procesador y “apunta” a la dirección de memoria de una variable.
Un arreglo es un conjunto de bytes continuos y acotados de un tipo de dato.

11. ¿A qué se conoce en computación como programación dinámica y memoria dinámica?


Explique detalladamente.

La programación dinámica

La programación dinámica es un método para reducir el tiempo de ejecución de un


método para reducir el tiempo de ejecución de un algoritmo mediante la utilización de
subproblemas superpuestos y subestructuras óptimas.

Es un método cuantitativo desarrollado por Richard Bellman alrededor de la década de


los años 50, con la finalidad de optimizar procesos, ya que en ese momento esa era su
función como trabajador de RAND Corporation. Bellman decidió emplear la palabra
dinámica a esta técnica, ya que deseaba analizar las variables de los problemas con respecto
al tiempo.

Siendo así Dasgupta, Papadimitriou y Vazirani (2006), entendieron a la programación


dinámica como “optimización de procesos con etapa múltiples”. La idea de Bellman sobre
la teoría de programación dinámica se basa en una estructura de optimización, la cual
consiste en descomponer el problema en subproblemas (más manejables).

Una «subestructura óptima» significa que se pueden usar soluciones óptimas de


subproblemas para encontrar la solución óptima del problema en su conjunto. Por ejemplo,
el camino más corto entre dos vértices de un grafo se puede encontrar calculando primero
el camino más corto al objetivo desde todos los vértices adyacentes al de partida, y después
usando estas soluciones para elegir el mejor camino de todos ellos. En general, se pueden
resolver problemas con subestructuras óptimas siguiendo estos tres pasos:

• Dividir el problema en subproblemas más pequeños.


• Resolver estos problemas de manera óptima usando este proceso de tres pasos
recursivamente.
• Usar estas soluciones óptimas para construir una solución óptima al problema
original.

La memoria dinámica

La memoria dinámica se refiere a aquella memoria que no puede ser definida ya


que no se conoce o no se tiene idea del número de la variable a considerarse, la solución a
este problema es la memoria dinámica que permite solicitar memoria en tiempo de
ejecución, por lo que cuanta más memoria se necesite, más se solicita al sistema operativo.
El sistema operativo maneja la memoria gracias al uso de punteros, por la misma naturaleza
del proceso nos impide conocer el tamaño de la memoria necesaria en el momento de
compilar.
Un dato importante es que como tal este tipo de datos se crean y se destruyen mientras se
ejecuta el programa y por lo tanto la estructura de datos se va dimensionando de forma
precisa a los requerimientos del programa, evitándonos así perder datos o desperdiciar
memoria si hubiéramos tratado de definir la cantidad de memoria a utilizar en el momento
de compilar el programa.

Cuando se crea un programa en el que es necesario manejar memoria dinámica el sistema


operativo divide el programa en cuatro partes que son: texto, datos (estáticos), pila y una
zona libre o heap. En la última parte es donde queda la memoria libre para poder utilizarla
de forma dinámica. En el momento de la ejecución habrá tanto partes libres como partes
asignadas al proceso por lo cual si no se liberan las partes utilizadas de la memoria y que
han quedado inservibles es posible que se «agote» esta parte y por lo tanto la fuente de la
memoria dinámica. También la pila cambia su tamaño dinámicamente, pero esto no
depende del programador sino del sistema operativo.

Memoria dinámica (Heap) en C++

La asignación dinámica de la memoria hace referencia a reservar un espacio en el


montón (heap) para almacenar una información. Esta forma requiere el uso de la palabra
reservada new para establecer el tamaño deseado del puntero:

La vida de los datos en el montón (heap) existe mientras el programador no los


elimine manualmente de la memoria, por ello cuando no necesitemos más la información
deberemos vaciar el espacio utilizando la palabra reservada delete, haciendo que el
programa devuelva la memoria al sistema operativo:
Por defecto el espacio reservado dinámicamente contiene información aleatoria,
pero podemos asignar el valor directamente en la definición:

Por cierto, no debemos eliminar un puntero ya vaciado, podría pasar cualquier cosa
en la memoria y dejar nuestro programa inservible:

En resumen:

12. Para qué sirven los comandos “new” y “delete”, como y donde se utilizan, indique
ejemplo.

El operador “new” se encarga de reservar memoria y “delete” de liberarla. Estos


operadores se emplean con todos los tipos del C++, sobre todo con los tipos definidos por
nosotros (las clases). La ventaja sobre las funciones de C de estos operadores está en que
utilizan los tipos como operando, por lo que reservan el número de bytes necesarios para
cada tipo y cuando reservamos más de una posición no lo hacemos en base a un número de
bytes, sino en función del número de elementos del tipo que deseemos.

El resultado de un “new” es un puntero al tipo indicado como operando y el


operando de un “delete” debe ser un puntero obtenido con “new”.

Veamos con ejemplos como se usan estos operadores:


int * i = new int; //reservamos espacio para un entero, i apunta
a él

delete i; //liberamos el espacio reservado para i

int * v = new int[10]; //Reservamos espacio contiguo para 10


enteros, v apunta al primero
delete []v; //Liberamos el espacio reservado para v

Hay que tener cuidado con el “delete”, si ponemos:

delete v;

Sólo liberamos la memoria ocupada por el primer elemento del vector, no la de los
10 elementos.

Con el operador “new” también podemos inicializar la variable a la vez que


reservamos la memoria:

int *i = new int (5); //reserva espacio para un entero y le asigna


el valor

En caso de que se produzca un error al asignar memoria con new, se genera una
llamada a la función apuntada por:

void (* _new_handler)(); //puntero a función que no retorna nada y no


tiene parámetros

Este puntero se define en la cabecera <new.h> y podemos modificarlo para que


apunte a una función nuestra que trate el error. Por ejemplo:
#include <new.h>

void f() {

...

cout << "Error asignando memoria" << endl;

...

void main () {

...

_new_handler = f;

...

También podría gustarte