Documentos de Académico
Documentos de Profesional
Documentos de Cultura
PUNTEROS
INDICE:
DESCRIPCION: PAGINA
INTRODUCCION ………………………………………… N° 01
char a;
scanf ("%c",&a);
DECLARACION DE PUNTERO:
Su sintaxis sería:
tipo *NombrePuntero = NULL; Se iguala a NULL para saber que no tiene
asignada ninguna dirección.
Donde tipo es el tipo de dato al que referenciará este puntero, es decir, que, si
se necesita guardar la dirección de memoria de un dato int, se necesita un puntero
de tipo int.
#include <stdio.h>
int main()
{
int a=0; //Declaración de variable entera de tipo entero
int *puntero; //Declaración de variable puntero de tipo
entero
puntero = &a; //Asignación de la dirección memoria de a
return 0;
}
Igual que cuando usamos un &, en la lectura de datos con scanf, igual de esta
forma lo usamos aquí, tal vez te acordarás que decíamos 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 carácter es la dirección
de inicio de la cadena.
¿Diferentes direcciones?
Tal vez notaste que en cada ejecución la dirección 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 dirección 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é que está haciendo esta dirección 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 dirección 0, esto quiere decir que existe,
lo que significa que le asignamos una dirección válida al puntero, pero el valor que
tiene NULL no se nos permite modificarlo, ya que pertenece al sistema.
Uso en funciones
OPERADORES:
OPERACIONES ARITMÉTICAS
PUNTEROS CONSTANTES
Es posible que hayas pensado cómo 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 decidir qué es lo que se quiere volver
constante, el valor -objeto- o la dirección?
Valor Constante:
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 hubiésemos hecho que el puntero fuese
una constante.
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.
Para recordar de una manera fácil, todo lo que está a la izquierda o antes del
“*“ es el tipo de dato al que apunta el puntero.
PUNTEROS GENÉRICOS
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
Anteriormente decíamos que una matriz es una secuencia de espacios en
memoria, que nos permitían alojar datos en cada uno y un puntero es una variable
que guarda la dirección de memoria, también decíamos cómo recorre las
direcciones de memoria con los operadores ++ y --.
#include <stdio.h>
int main()
{
for (i=0;i<10;i++)
printf("%d\n",*(puntero+i)); //imprimimos los valores del puntero
que es equivalente a imprimir los valores del arreglo.
return 0;
}
Para poder modificar el valor de este puntero, este tendría que apuntar a una
dirección que no sea una constante, como un array.
Esta vez pudiste notar que sí se pudo remplazar el valor del nombre, pero aun
la cantidad de caracteres está limitada por el array original, mas adelante veremos
cómo solucionar esto con memoria dinámica.
MATRICES DE PUNTEROS
Ejemplo:
#include <stdio.h>
int main()
{
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 dirección de memoria de un puntero, el cual a
su vez contiene la dirección de memoria de un tipo de dato. Se usa ** para definir un
puntero a un puntero. Recuerden que un puntero sigue siendo un espacio en
memoria, pero en vez de almacenar un valor almacena una dirección.
Si decimos que:
EJEMPLOS
Tenga en cuenta el siguiente bloque de código que declara 2 punteros
pPointer = &myInt;
pKeyboard = &dvorak;
#include <stdlib.h>
...
struct MyStruct *pKeyboard;
...
pKeyboard = malloc(sizeof(struct MyStruct));
...
if (b == 1) myReturn = &val1;
else if (b==2) myReturn = &val2;
else if (b==3) myReturn = &val3;
else myReturn = &val4;
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 */
PUNTEROS Y FUNCIONES:
int *p;
p= (int *) malloc(50*sizeof(int));
PUNTEROS Y ESTRUCTURA:
a.x = 5;
a.y = 23;
a.z = 10;
b = a;
p = &b; /* &b nos devuelve la dirección de la estructura b */
p->x = 2;
p->y = a.y;
p->z = a.z;
vector_punteros_coordenadas[4] = &coor1;
vector_punteros_coordenadas[4]->y = 2;
Al igual que ocurría con los punteros a tipos básicos de datos también se
pueden pasar punteros a estructuras en las llamadas a funciones. Así por ejemplo
tendríamos:
struct coordenada coordenada1, *p_coordenada1;
flota distancia;
..................................
coordenada1.x = 5;
coordenada1.y = -11;
p_coordenada1 = &coordenada1;
..................................
cambiar_a_punto_simétrico_en_cuadrante (p_coordenada1);
cambiar_a_punto_simetrico_en_cuadrante (&coordenada1);
..................................
....
....
....
{
int aux;
aux = (*c).x;
(*c).x = (*c).y;
(*c).y = aux;
}
Teniendo en cuenta todo lo antes descrito se puede llegar a concluir que su uso
permite el paso de argumentos por referencia, la construcción de estructuras
dinámicas de datos y la mejora en la velocidad de ejecución de algunos algoritmos.
Sin embargo, mal usados pueden producir errores graves, difíciles de detectar y, en
ocasiones, los peores errores posibles: los no reproducibles.