Documente Academic
Documente Profesional
Documente Cultură
PUNTERO
Estudian
tes:
Gil, Alexis
V-24.886.445
XFzzzzzzzzzzzzz xzc
DECLARANDO PUNTEROS
Ya se dijo que un puntero es una variable que guarda la direccin de memoria de
otra variable, haciendo lgica a esto, decimos que un puntero se declara igual que cualquier
otra variable, pero anteponiendo un * (asterisco) antes del nombre de la variable.
Su sintaxis seria:
tipo *Nombre Puntero;
Donde tipo es el tipo de dato al que referenciar este puntero, es decir, que si se necesita
guardar la direccin de memoria de un dato int, se necesita un puntero de tipo int.
EXPLICACIN
Veamos el siguiente codigo:
include <stdio.h>
int main()
{
int a=0; //Declaracin de variable entera de tipo entero
int *puntero; //Declaracin de variable puntero de tipo entero
puntero = &a; //Asignacin de la direccin memoria de a
printf("El valor de a es: %d. \nEl valor de *puntero es: %d. \n",a,*puntero);
printf("La direccion de memoria de *puntero es: %p",puntero);
return 0;
#}.
Igual que cuando usamos un &, en la lectura de datos con scanf, igual de esta forma
lo usamos aqu, tal vez te acordaras que decamos que las cadenas de caracteres (%s) no
usaban este operador, esto es porque en una cadena de caracteres es un arreglo de
caracteres, por lo que el primer carcter es la direccin de inicio de la cadena El operador *,
nos permite acceder al valor de la direccin del puntero, en este caso nos permite acceder al
valor que contiene a la variable a. De esta forma "a" y "*puntero" muestran el mismo dato,
pero esto no quiere decir que sea lo mismo, uno es un entero el otro un puntero.
La impresin con %p, es para poder imprimir la direccin de memoria en valor
hexadecimal (0x...), tambin podemos imprimir: ...%p",&a) y funciona de la misma
forma, y es lgico que tanto a, como puntero tienen la misma direccin de memoria.
DIFERENTES DIRECCIONES
Tal vez notaste que en cada ejecucin la direccin de memoria cambia, esto es
porque es el sistema operativo quien est encargado de administrar la memoria y es ste
quien dice qu espacios podr tomar el programa.
Esto quiere decir que uno no puede asignarle una direccin de memoria a un
puntero directamente, es decir yo no puedo hacer lo siguiente.
int *puntero=0xbfc5b1c8;
Esto no puedo ni debo hacerlo ya que yo no s qu est haciendo esta direccin de
memoria, si el sistema la tiene o no disponible, etc... Pero s puedo hacer esto:
int *puntero=NULL;
NULL, es el espacio en memoria con direccin 0, esto quiere decir que existe, lo que
significa que le asignamos una direccion vlida al puntero, pero el valor que tiene NULL no
se nos permite modificarlo, ya que pertenece al sistema.
OPERADORES
Ya anteriormente te ponamos algunos ejemplos de cmo asignar la direccin de
memoria a un puntero y de cmo acceder al valor de este.
Operador de Direccin (&):
Este nos permite acceder a la direccin de memoria de una variable.
Operador de Indireccin (*):
Adems de que nos permite declarar un tipo de dato puntero, tambin nos permite
ver el VALOR que est en la direccin asignada.
Incrementos (++) y Decrementos (--): Te dars cuenta que puedes usar un puntero
como si de un array se tratase, es por esto que permite estos operadores.
De lo anterior podemos decir que:
int a; Es Igual int *puntero=&a; printf("%d",a); Es Igual printf("%d",*puntero);
OPERACIONES ARITMTICAS
Un puntero nos permite sumar o restar nmeros enteros, pero su funcionamiento
ahora es de posiciones, es decir que nos permitir movernos a la siguiente direccin de
memoria.
A un puntero no se le puede realizar multiplicaciones, divisiones, sumas o restas con
otro puntero o con un valor de tipo coma flotante (float, double...). Esto es por que un
puntero no es un valor, slo es una direccin.
En un puntero se pueden realizar varias operaciones de tipo enteras, pero en
dependencia de como se usen, sus resultados pueden ser muy diferentes, a continuacin les
muestro algunas de estas operaciones:
//Definamos estas variables:
int x[100],b,*pa,*pb;
//...
x[50]=10; //Le asignamos el valor de 10, al array #50
pa=&x[50]; //Le asignamos al puntero pa, la direccion de memoria que tiene x[50]
//Ahora mostramos algunas posibles operaciones:
b = *pa+1; //Esto es como decir el valor que tiene el array de x[50] sumarle 1.
//Esto es igual a: b=x[50]+1; => Su valor seria igual a 11.
b = *(pa+1); //Esto primero pasa a la siguiente direccion de memoria y luego lo referencia
//El resultado es: b = x[51];
pb = &x[10]; //al puntero pb se le asigna la direccion de x[10]
*pb = 0; //Al valor que tiene el puntero se le asigna
//Esto es igual que decir: x[10] = 0
*pb += 2; //El valor del puntero se incrementa en dos unidades, es decir x[10] = 2(*pb)--;
//El valor del puntero se decrementa en una unidax[0] = *pb--; //A x[0] se le pasa
valodex[10] y el puntero pb, pasa a apuntar a x[9] //recuerda, que -- es post-incremento,
primero asignara y luego restara.
PUNTEROS CONSTANTES
Es posible que hayas pensado como declarar un puntero como una constante, tal vez
pensaste en un #define, o en un atributo const. Bueno es posible usar el atributo const, pero
para un puntero hay que hacerlo de otra forma.
FORMA ERRADA:
int a=10,b=20;
const int *p = &a; //objeto constante y puntero variable
*p = 15; // ERROR: el valor apuntado por p es constante.
p=&b; //Correcto: p pasa a apuntar a un nuevo objeto.
Pero de esta forma no es muy til declararlo, pues el que hicimos constante fue el
valor al que apunte p, es decir, mejor hubisemos hecho que el puntero fuese una constante.
FORMA CORRECTA:
int a=10,b=20;
int * const p = &a; //objeto variable y puntero constante
*p = 15; // Correcto: El valor apuntado es variable.
p=&b; //ERROR: p es constante.
PUNTEROS GENRICOS
Un puntero a cualquier tipo de dato puede convertirse a un puntero del tipo void *.
Por esto un puntero a void *, recibe el nombre de puntero genrico.
En C, se permite la conversin implcita de punteros, pero en C++ esto no es posible, as
que por compatibilidad y buena practica recomendamos usar la conversin explcita (cast).
Supongamos:
int *puntero;
funcion (*puntero);
....
void funcion (void *p)
int *q;
q=(int *)p; //En C se podria hacer q = p;
Es decir que un puntero a void se puede usar sin importar el tipo de dato, recuerden
que uno no puede trabajar con punteros que referencia a un tipo de dato diferente, como lo
es un puntero a char, con un puntero a int.
PUNTEROS Y MATRICES
MATRICES DE PUNTEROS
Es muy probable que ya te hayas dicho: Si un puntero es una variable, Puedo tener un
array de punteros? La respuesta seria NO Exactamente.
Como ya habiamos explicado antes, un puntero trabaja de la misma forma que un array,
tanto que podemos decir que un puntero es un array, entonces si definimos un array de un
array, nos dara como resultados un array bidimensional.
En la prctica es mucho ms comn utilizar un array de punteros que un array
bidimensional.
Hay que recordar que siguen siendo punteros, es decir slo apuntan a una direccin de
memoria, por ende hay que asignarles la direccin de memoria a cada uno de los elementos
del puntero. Sin embargo podemos asignar en un solo ciclo todas las filas.
Ejemplo:
#include <stdio.h>
int main()
{
int *puntero[5]; //array de puntero
int a[5][5]; //Array bidimensional.
int i;
for (i=0;i<5;i++)
puntero[i]=a[i]; //Asignamos las filas al puntero.
//Pueden imprimir tambien en un ciclo
//Tambien pueden acceder mediante un ciclo anidado a la
variables del puntero[i][j]
}
PUNTEROS A PUNTEROS
Es una variable que contiene la direccin de memoria de un puntero, el cual a su vez
contiene la direccin de memoria de un tipo de dato. Recuerden que un puntero sigue
siendo un espacio en memoria, pero en vez de almacenar un valor almacena una direccin.
Si decimos que:
int a=0; //Supongamos que es una variable cuya direccion es 0x1601
int *puntero1=&a; //El puntero tiene guardada la direccion de a,
//pero este tiene como direccion 0x1890
int **puntero2=&puntero1; //**puntero 2 guarda la direccion 0x1890
Ahora se entiende mejor. Al uso de punteros se le llama variables con niveles de
indireccion, ya que no apuntan directamente a un valor, sino que apuntan a alguien que lo
tiene. Basndonos en esto podemos decir que *puntero1 esun puntero con un nivel de
indireccion y *puntero2 es un puntero con dos niveles de indireccion.
En general estos tipos de datos son usados con matrices multidimensionales.
MATRICES DE PUNTEROS A CADENAS DE CARACTERES
No hablaremos sobre este tema, debido a que es prcticamente una matriz de caracteres
que se usa mediante punteros, y esto es tcnicamente lo mismo que hemos estado viendo
anteriormente.
Tambin podemos usar punteros a punteros y guardar mltiples cadenas.
Ejemplos Tenga en cuenta el siguiente bloque de cdigo que declara 2 punteros
/*1*/ struct MyStruct {
/*2*/ int m_aNumber;
/*3*/ float num2;
/*4*/ };
/*5*/
/*6*/ int * pJ2;
/*7*/ struct MyStruct * pAnItem;
Las primeras 4 lneas definen la estructura. La linea 6 declara una variable que apuntar a
un entero, y la lnea 7 declara una variable que apunta a algo de la estructura MyStruct.
Entonces declarar un puntero es algo que apunta a algo de algn tipo, ms que contener el
tipo. El asterisco ( * ) se coloca antes del nombre de la variable.
En las siguientes lneas de cdigo, var1 es un puntero a un entero largo ( long )
mientras var2 es un entero largo ( long ) y no un puntero a un entero largo. En la segunda
lnea se declara p3 como un puntero a un puntero de un entero.
long * var1, var2;
int ** p3;
Los punteros se usan habitualmente como parmetros de funciones. El siguiente cdigo
muestra como declarar una funcin que usa un puntero como argumento. Teniendo en
cuenta que C pasa todos los argumentos por valor, para poder modificar un valor desde el
cdigo de la funcin, se debe usar un puntero al valor a modificar. Tambin se usan
punteros a estructuras como argumentos de una funcin an cuando la estructura no sea
modificada dentro de la funcin. Esto es realizado para evitar copiar todo el contenido de la
estructura dentro de la pila.
return myReturn;
}
...
struct MyStruct *strPointer;
int *c, *d;
int j;
...
c = &j; /* puntero asignado usando el operador & */
d = c; /* asignando un puntero a otro */
strPointer = ASillyFunction( 3 ); /* puntero retornado de la funcion */
Cuando se retorna un puntero de una funcion, se tiene que tener cuidado de que el valor
apuntado no sea de una referencia de una variable local a la funcion, porque estos valores
desaparecen despues de salir de la funcion y el puntero estaria mal referenciado, causando
errores en tiempo de ejecucion en el programa. La memoria creada dinamicamente dentro
de la funcion puede devolverse como puntero, el valor de retorno aunque es creado en una
variable local la direccion como tal se devuelve por valor dejando esta informacion valida.