PDF de programación - Punteros

Imágen de pdf Punteros

Punterosgráfica de visualizaciones

Publicado el 14 de Enero del 2017
1.046 visualizaciones desde el 14 de Enero del 2017
143,6 KB
15 paginas
Creado hace 15a (12/12/2005)
Punteros



Definición
Un puntero es un dato que contiene una dirección de memoria.


NOTA:

Existe una dirección especial que se representa por medio de la
constante NULL (definida en <stdlib.h>) y se emplea cuando
queremos indicar que un puntero no apunta a ninguna dirección.



Declaración

<tipo> *<identificador>



<tipo>
Tipo de dato del objeto referenciado por el puntero
<identificador>
Identificador de la variable de tipo puntero.



Cuando se declara un puntero se reserva memoria para albergar una dirección de
memoria, pero NO PARA ALMACENAR EL DATO AL QUE APUNTA EL PUNTERO.

El espacio de memoria reservado para almacenar un puntero es el mismo
independientemente del tipo de dato al que apunte: el espacio que ocupa una
dirección de memoria.



char c = ’a’;
char *ptrc;
int *ptri;

Operaciones básicas con punteros



Dirección
Operador &

&<id> devuelve la dirección de memoria donde comienza la variable <id>.

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



int i;
int *ptr;
...
ptr = &i;

Indirección
Operador *

*<ptr> devuelve el contenido del objeto referenciado por el puntero <ptr>.

El operador * se usa para acceder a los objetos a los que apunta un puntero:



char c;
char *ptr;

ptr = &c;
*ptr = ‘A’; // Equivale a escribir: c = ‘A’

Asignación
Operador =


A 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;



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



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



Otro puntero del mismo tipo:


char c;
char *ptr;
...
ptr = &c;

char c;
char *ptr1;
char *ptr2;

ptr1 = &c;
ptr2 = ptr1;

Ejemplo

int main ()
{
int y = 5;
int z = 3;
int *nptr;
int *mptr;


nptr = &y;



z = *nptr;



*nptr = 7;



mptr = nptr;



mptr = *z;



*mptr = *nptr;



y = (*nptr) + 1;

return 0;
}



Errores comunes

Asignar punteros de distinto tipo


int a = 10;
int *ptri = NULL;
double x = 5.0;
double *ptrf = NULL;
...
ptri = &a;
ptrf = &x;
ptrf = ptri;

// ERROR



Utilizar punteros no inicializados



char *ptr;
*ptr = ‘a’;

// ERROR



Asignar valores a un puntero y no a la variable a la que apunta


int n;
int *ptr = &n;


ptr = 9;

// ERROR



Intentar asignarle un valor al dato apuntado por un puntero cuando éste es NULL


int *ptr = NULL;

*ptr = 9;



// ERROR

Punteros a punteros

Un puntero a puntero es…
un puntero que contiene la dirección de memoria de otro puntero-


int main ()
{
int a = 5;
int *p;
int **q; // Puntero a puntero



p = &a;



q = &p;
}



Para acceder al valor de la variable a podemos escribir



a
*p
**q (a través del puntero a puntero q)

(forma habitual)
(a través del puntero p)

// Puntero a entero

q contiene la dirección de p, que contiene la dirección de a



Aritmética de punteros
Correspondencia entre punteros y vectores


Cuando declaramos un vector



en realidad


<tipo> <identificador> [<dim>]

1. Reservamos memoria para almacenar <dim> elementos de tipo <tipo>.

2. Creamos un puntero <identificador> que apunta a la primera

posición de la memoria reservada para almacenar los componentes del
vector.


Por tanto, el identificador del vector es un puntero.

int v[3];
int *ptr;
...
ptr = v; // Equivale a ptr = &v[0]
v[0] = 6; // ≡ *v = 6; ≡ *(&v[0]) = 6;



Aritmética de punteros

<tipo> *ptr;

ptr + <desplazamiento> devuelve un puntero a la posición de memoria
sizeof(<tipo>)*<desplazamiento> bytes por encima de ptr.


int v[];
int *ptr = v; ptr+i apunta a v[i]



*(ptr+i) ≡ v[i]



NOTA: La suma de punteros no tiene sentido y no está permitida. La resta sólo
tiene sentido cuando ambos apuntan al mismo vector y nos da la “distancia”
entre las posiciones del vector (en número de elementos).

/* Alternativa 1 */



/* Alternativa 2 */

Ejemplo: Distintas formas de sumar los elementos de un vector

int suma ( int v[], int N)
{
int i, suma;
int *ptr, *ptrfin;

suma = 0;
for (i=0 ; i<N ; i++)
suma = suma + v[i];



suma = 0;
for (i=0 ; i<N ; i++)
suma = suma + (*(v+i));



suma = 0;
ptrfin = ptr + N-1;
for (ptr=v ; ptr<=ptrfin ; ptr++)
suma = suma + *ptr;

return suma;
}



/* Alternativa 3 */

Punteros y matrices
<tipo> mat [<dimF>][<dimC>];



dirección(i,j) = dirección(0,0) + i*dimC + j



Ejemplo: Intercambio de valores


void Cambia(int *a, int *b)
{
int aux;

aux = *a;
*a = *b;
*b = aux;
}

int main()
{
int x=0, y=1;

Cambia(&x,&y);

return 0;
}



Gestión dinámica de la memoria


Organización de la memoria


‐ Segmento de código (código del programa).

‐ Memoria estática (variables globales y estáticas).

‐ Pila (stack): Variables automáticas (locales).

‐ Heap (“montón”): Variables dinámicas.



ANSI C:
C++:

Función malloc
Operador new


Reserva y liberación de memoria

Cuando se quiere utilizar el heap, primero hay que reservar la memoria que se
desea ocupar:



Al reservar memoria, puede que no quede espacio libre suficiente, por lo que
hemos de comprobar que no se haya producido un fallo de memoria (esto es, ver
si la dirección de memoria devuelta es distinta de NULL).

Tras utilizar la memoria reservada dinámicamente, hay que liberar el espacio
reservado:



Si se nos olvida liberar la memoria, ese espacio de memoria nunca lo podremos
volver a utilizar…



Función free
Operadore delete

ANSI C:
C++:

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

return suma/n;

suma += v[i];

Ejemplo: Vector de tamaño dinámico

#include <stdio.h>
#include <stdlib.h>

float media (float v[], int n)
{



}


int main(int argc, char *argv[])
{



}


int i;
int n;
float *v;
printf("Número de elementos del vector: ");
scanf("%d",&n);
// Creación del vector
v = malloc(n*sizeof(float));
// Manejo del vector
for (i=0; i<n; i++)

printf("Media = %f\n", media(v,n));
// Liberación de memoria
free(v);

return 0;

v[i] = i;

int usado; // Elementos usados del vector
int capacidad; // Capacidad del vector

Ejemplo: TDA Vector Dinámico


Tipo de los elementos del vector dinámico

typedef int Dato;

Estructura de datos del vector

typedef struct Vector {
Dato *datos; // Vector de datos


};

typedef struct Vector *Vector;


Creación del vector (constructor)

Vector crearVector (void)
{
Vector v =(Vector) malloc ( sizeof(struct Vector) );

v->usado = 0;
v->capacidad = 2;
v->datos = malloc ( (v->capacidad)*sizeof(Dato) );

return vector;
}

Destrucción del vector (destructor)

void destruirVector (Vector *v)
{
free ( (*v)->datos );
free ( *v );

*v = NULL;
}

Constructor y destructor nos permiten manejar vectores sin
tener que conocer su estructura de datos interna (ni siquiera
tendremos que utilizar malloc y free).

Acceso al contenido del vector
Funciones que permiten ocultar los detalles de implementación del TDA


Número de elementos del vector:


int elementosVector (Vector v)
{
return v->usado;
}


Acceso a los elementos concretos del vector:


Obtención del valor almacenado en una posición del vector:


Dato obtenerDato (Vector v, int pos)
{
if ((pos>=0) && (pos<elementosVector(v)))
return v->datos[pos];
else
return NULL;
}


Modificación del valor almacenado en una posición del vector:


void guardarDato (Vector v, int pos, Dato dato)
{
if ((pos>=0) && (pos<elementosVector(v))) {
v->datos[pos] = dato;
}
}


for (i=0; i < v->usado; i++)

datos[i] = v->datos[i];
free(v->datos);
v->datos = datos;

Inserción de datos

void agregarDato (Vector v, Dato dato)
{
int i;
Dato *datos;

if (v->usado == v->capacidad) {

// Redimensionar el vector
v->capacidad *= 2;
datos = malloc ( (v->capacidad)*sizeof(Dato) );



}

v->datos[v->usado] = dato;
v->usado ++;
}

Eliminación de datos

void eliminarDato (Vector v, int pos)
{
int i;

if ((pos>=0) && (pos<elementosVector(v))) {


for (i=pos; i<elementosVector(v)-1; i++)

v->datos[i] = v->datos[i+1];


v->usado --;
}
}



¡OJO!

En la implementación mostrada no contemplamos la
posibilidad de que la función malloc devuelva NULL
(algo que siempre deberemos hacer al programar).

Ejemplo de uso del TDA Vector Dinámico


#include <stdio.h>
#include “vector.h”

/* Rutina auxiliar */

void mostrarVector (Vector v)
{
int i;

printf( "Vector de tamaño %d:\n",
elementosVector(v) );

for (i=0; i<elementosVector(v); i++)
printf("- %d\n", obtenerDato(v,i));
}


/* Programa principal */

int main ()
{
Vector v = crearVector();

mostrarVector (v);

agregarDato (v,1);
agregarDato (v,2);
agregarDato (v,3);
mostrarVector (v);

eliminarDato (v,1);
mostrarVector (v);

guardarDato (v, 0, obtenerDato(v,0)+2);
mostrarVector (v);

destruirVector(&v);

return 0;
}
  • Links de descarga
http://lwp-l.com/pdf788

Comentarios de: Punteros (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad