Está en la página 1de 47

TIPOS DE DATOS

PUNTEROS
OBJETIVOS

 Manejo De punteros y reserva de memoria dinámica


 Utilizar correctamente las estructuras, punteros a
estructuras, arreglos de estructuras, entre otros.
DATO
 Información en bruto, sin ningún significado
 Dado un enunciado, evento o acción, los datos
 Permiten representar sus actores o participantes
 Analizándolos, se podrá obtener resultados deseados
 Analicemos el siguiente hecho:
 El estudiante de nombre Pedro Velez de 22 años, tiene un promedio de 4.5
 Podemos tomar los siguientes datos
 Nombre: Pedro Velez -> Conjunto de Caracteres
 Edad: 22 -> entero
 Promedio: 4.5 -> real
INFORMACIÓN
 Es el resultado deseado luego de procesar los datos
 Los datos, al ser procesados, se convierten en
información útil o resultados.

Empleado Horas Datos de salida(se muestran


Juan, Perez 160 en el monitor)
Pedro, Rodriguez 155 Juan, Perez $320
Luis, Pozo 120 Pedro, Rodriguez $310
Luis, Pozo $240
Valor por hora = $2

Datos de entrada(ingresados x
teclado) Procesamiento:
Calcular salarios
¿Cómo representar los datos?
 Los seres humanos:
 Usamos lenguaje natural o símbolos
 Ejemplo:
 Para representar números, usamos el sistema decimal
 Para representar palabras, usamos el abecedario
 Las maquinas de computo:
EN
 Usa conjuntos de unos y ceros 01010101010111000 SERIO!!!
 El dato mas pequeño en el computador es
 Un 1 o un 0 -> bit
 El conjunto de 8 bits -> 1 byte
TIPOS DE DATOS
 Los datos se clasifican en TIPOS
 Son los diferentes dominios existentes. Ejemplo:
 Edad, Año de Nacimiento, Numero de multas
 Tienen dominio numérico
 Nombre, Dirección, Lugar de nacimineto,
 Caen en el dominio de la información tipo texto

 Y las operaciones permitidas para dicho dominio


Un conjunto de valores y operaciones
definidas solo para esos valores
RECORDAR
 Un tipo de dato es el conjunto de valores
 Al que puede pertenecer una constante
 Que puede asumir una variable o expresión
 Que puede ser generado por una función
 De una constante, variable o expresión
 Se puede deducir su tipo de dato
 Ya sea de su forma o de su declaración
 Sin necesidad que se ejecute ningún proceso
 Las operaciones entre datos
 Necesitan participantes (argumentos) de determinado tipo
 Producen resultados de otro o el mismo tipo
TIPOS DE DATOS BASICOS
 Los podemos distinguir fácilmente, están en el diario vivir:
 El Sr. Vera de 63 años tiene cedula No. 908815533, y paga $120 de
impuestos
 Son tipos de datos simples
 Que permiten representar información numérica, caracteres, etc.

NOMBRE CONJUNTO DE VALORES OPERACIONES


Enteros Negativos y positivos sin decimal Sumar, restar, dividir, multiplicar,
residuo
Reales Negativos y positivos, con decimal Sumar, restar, dividir, multiplicar
Lógicos Verdadero o Falso(1 o 0) And, Or, Not
Caracteres Letras, números, especiales, juntos Sumar carácter + entero restar,
forman una cadena multiplicar por entero
Y EN LA COMPUTADORA?
 Solo vienen integrados los tipos de datos básicos 1000
1001
 En la computadora
1002
 Cada byte es una caja y tiene una dirección en memoria
1003
 Los datos (números y letras) se almacena en estas cajas
 ¿Cuantas cajas ocupa un dato?
 Depende de su tipo y del hardware de la computadora
 Un entero puede ocupar casillas de hasta 4 bytes
 Un doble siempre ocupara mas, por su mayor precisión
 PERO, un carácter SIEMPRE ocupara cajas de 1 byte
ALMACENANDO DATOS
TIPO DE DATO #bytes Representación interna En ANSI C

ENTEROS 2 Positivos: conjunto de bits int


4 38 -> 00100110 long
8 Negativos:Complemento a Dos
-38 -> 11011001
REALES 8 Mantisa x base(exponente) float
16 387.53 -> 38753 x 10-2 double
00000000100101110110000111111110
CARACTERES 1 ASCII char
11000000 -> ‘A’
DECLARACION DE Al declarar una variable se
le asigna espacio en

VARIABLES memoria y una dirección


para dicho espacio

 Una declaración de variables en C++ incluye


 Tipo de dato y
 Nombre de variable(identificador) 100
4 bytes,
int a; 101
 Ejemplo: dir: 100
102
int a, b; char c; 103
1 byte,
104
float c; dir: 104

 ¿Para que se declaran variables?


 Especifica cuanta memoria debe reservarse y
 Como se van a interpretar dichos datos
f = a + b
 Es una suma de enteros, que al final se convierte a real
DIRECCIONES DE
MEMORIA
 Las variables
 Tienen direcciones de memoria
 Si deseamos conocer dicha dirección
 En lenguaje C++
 Se usa el operador & de dirección
1000
&a es
 Ejemplo: 1001 1000
int a;
a = 3; 1002
printf(“Valor:%d Dir: %d”, a, &a);
1003
 Un puntero
 Es una variable que puede almacenar dirección de
memoria
DECLARACION DE
PUNTEROS
int *p;
 Un tipo de dato
 El puntero solo podrá almacenar direcciones de
memoria de variables del tipo especificado
1000
 Se pueden definir punteros de cualquier tipo: 1001 3 x
1002
float *pf; 1003
char *pc; 1004
1005
1000 pt
 Un identificador que siempre va antecedido del operador *
int *pt, x; pt almacena la
x = 3; dirección de x, se dice
pt = &x; que pt apunta a x
CONSULTANDO CONTENIDO
 Si un puntero apunta a una variable
 A través del puntero se puede llegar a conocer todo sobre la variable
 Ejemplo: char c, *pc1, *pc2;
pc1 = &c;

 Si quiero conocer la dirección, uso directamente el puntero


printf(“%d”, pc1); //Imprimo la dir. Almacenada por pc1
pc2 = pc1; //pc2 almacena la misma dir. que pc1

 Si quiero conocer el contenido al que apunta un puntero, uso el


operador *, sobre dicho puntero Es equivalente a :
printf(“%c”, c);
c = ‘A’
printf(“%c”, *pc1); Es equivalente a :
c = ‘N’
*pc1 = ‘N’
printf(“%c”,c); Imprime ‘N’ pues c ya
cambio
EJERCICIO EN CLASE
int x,y;
int *p1,*p2;
1000 -42
17
22 x
x = -42;
y = 163; 1004 163
22 y
p1 = &x;
1008 1000
1004
1000
1004
0 p1
p2 = &y;
*p1 = 17; 1012 1004
1004
0 p2
*p2 = x+5;
*p1 = *p2;
Es equivalente a escribir
x = y;
p1 = p2; Esto indica que p1
ahora apunta a la
p1 = NULL; misma variable que p2

p2 = NULL; Esto es equivalente a “encerrar” el


puntero, y decir que no apunta a ninguna
variable
PASO DE PARAMETROS
 Las funciones son porciones de código
 Ejecutan una tarea especifica
 Usualmente toman datos de entrada->parámetros
 Y retornan un valor

 Los parámetros se pueden enviar de dos formas:


 Por valor
 Por referencia
PASO POR VALOR
 La función no recibe la variable enviada
 Recibe una copia
 Similar a cuando va al hacer algún tramite y le piden al cédula
 No entrega la cédula verdadera
 Entrega una copia
 La verdadera estará segura, aunque quemen y destruyan la copia
 Ejemplo: x = 5
printf(“%d\n”,x);
Se imprime 5, el valor de x no
funct(x); cambia aunque la función haya
printf(“%d\n”,x); intentado modificarla

void funct(int y){


y = y+1;
printf(“%d\n”,y);
}
PASO POR REFERENCIA
 Aquí si la función recibe exactamente la variable enviada
 No hay copias
 Si algo se le hace al parámetro, se le esta haciendo a la variable
 Para esto, se usan punteros
 La función trabaja con un puntero a la variable enviada
 Sabe todo sobre esa variable y se pude acceder a través de *
 Ejemplo: x = 5
printf(“%d\n”,x); Se imprime 6, el valor de x cambió
funct(&x); dentro de la función
printf(“%d\n”,x);
void funct(int *py){
*py = *py+1;
printf(“%d\n”,*py);
}
TIPOS DE DATOS
COMPUESTOS
 En ocasiones se necesitan TIPO FORMATO Bytes
DECLARACION
tipos de datos mas complejos,
ARREGLOS int arrEj[10]; 10*2 = 20
y estructurados
 Variables que almacenen mas de ESTRUCTURAS typedef struct TReg{ 2 + 100 =
un valor int ID; 102
char Texto[100];
 Variables que representen
}Reg;
información de la vida real UNIONES typedef union TUn{ 100
 Estarán formados a partir de int ID;
tipos de datos simples char Texto[100];
}Un;
 En C++, tenemos:
ARREGLOS
 Conjunto de elementos
 Finito, Ordenado y Homogéneo,
 Todos sus elementos son del mismo tipo
 Un arreglo estático se declara
int A[100];
 El tipo de los elementos, el identificador y A
 El numero de elementos (dimensión)
0 1 2 3 4 ... 99
 Cada elemento del arreglo tiene un índice
 En C, siempre el índice mas pequeño es el 0: limite inferior
 El limite superior, es 1 menos que la dimensión
 Si el arreglo tiene 100 elementos, el índice mas alto es el 99
 Y si un entero ocupa 4 bytes, el arreglo ocupa 400 bytes
seguidos
Tipo de dato:

OPERACIONES Conjunto de valores y operaciones


definidas solo para esos valores

 No basta con la declaración, para ser tratado como un tipo


de dato
 Faltan las operaciones para actuar sobre él
 Consulta de un elemento
//Consulto el contenido de los elementos 4 y 5 de A
printf(“%d %d”,A[4], A[5]);

 Modificación de un elemento
A[3] = 2; //Almaceno un valor en el elemento 3 de A
for(i = 0; i < 100; i++)
A[i] = 0;
REPRESENTACION INTERNA
 Cuantos bytes ocupa un tipo de dato o variable? 1000 Lista[0]
 En C++ lo indica el operador sizeof
 Ejemplo:
1008 Lista[1]
int a;
printf(“%d %d”, sizeof(int), sizeof(a));
1016 Lista[2]
 El computador internamente
 No almacena la dirección de todos los elementos del
arreglo 1024 Lista[3]
 Solo almacena la dirección del primer elemento
Lista[4]
 El resto lo calcula así: 1032

&Lista[i] -> &Lista[0] + (i*sizeof(Lista[0]))


RESERVA DE MEMORIA
DINAMICA a no apunta a otra
variable, tiene
memoria propia,
solo para el
 La declaración de una variable
 Siempre reserva memoria
 Aunque la variable no se use, ya se reservo memoria para ella: ESTATICA
 Si deseamos reservar memoria, pero no en la declaración
 Si no, a voluntad dentro del programa int *a; //No se reserva nada
..
 La reserva seria dinámica /*Cuando se desee, se reserva*/
a = malloc(sizeof(int));
 En C++ se usan //La variable normalmente
*a = 3;
 Punteros y #include <stdlib.h>
void *malloc(size_t size);
 Las funciones de librería
ARREGLOS DINAMICOS
 En ocasiones deseamos usar arreglos
 Donde no hayamos “predefinido” cuantos elementos max. tendremos
 Queremos usar arreglos dinámicos
 Se declara el arreglo “potencial”:
int *arreglo;

 Dentro del programa, se pide memoria cuando se necesite:


arreglo = malloc(sizeof(int)*20); Para indicar el nuevo tamaño se puede
main(){ usar una constante o una variable,o
cualquier expresión
int *arreglo, n;
printf(“Ingrese el tamaño del arreglo:”);
n = GetInteger();
arreglo = malloc(sizeof(int)*n);
printf(“Ahora tiene %d elementos para trabajar\n”,n);
...
}
Y LIBERA..
 Al pedir memoria dinámicamente
 Se debe liberar dentro del programa
 En C++ se libera usando la función free

Cuando se
libera para
una
int *a; variable
a = malloc...;

free(a);
ARITMETICA DE PUNTEROS
 Los operadores + y –
 Se pueden usar con punteros
 Pero el significado de la operación cambia un poco
 Si un entero ocupa 4 bytes, tomemos este ejemplo
int x; La suma indica que p se mueva 2
“enteros” mas adelante
int *p; Cada entero equivale a 4 bytes
p = &x; 100 + 2*4 = 108

 Si la dirección de x es un valor 100 y decimos


p = p+2;
 Que dirección almacena p?
102 108 104
p2
EJERCICIO EN CLASE
main(){
double Lista[3]; p 1000
double *p,*p1,*p2; Lista[0]
1
int k; 1008
Lista[0] = 1; 1.1 Lista[1]
Lista[1] = 1.1;
Lista[2] = 1.2; 1016
p = Lista; Lista[2]
p se mueve 2 1.2
p = p + 2; desfases
printf("*p= %d con suma ", *p); p1
p = p - 1;
p retrocede un
printf("\n *p= %d con resta ", *p);
desfase
p1 = Lista+2;
p2 = &Lista[0];
k = p1-p2; Da el total de desfases
printf("\n k= %d ", k); entre p1 y p2
}
PASO DE ARREGLOS A
FUNCIONES
 Al pasar un arreglo a una función debe tomarse en cuenta
 ¿Necesitare también el tamaño del arreglo?
 Si es así, también debe incluirse como parámetro
 En prototipos y cabecera
float CalcPromedio(float A[], int size);
float funct(float B[]);

 En el cuerpo de la función
float CalcPromedio(float A[], int size){
…..
A[i] = 3;
}

 Siempre recuerde que


 El paso de arreglos, es un paso por referencia
ARREGLOS
BIDIMENSIONALES
 La programación ofrece innumerables opciones
 Un elemento de un arreglo, puede ser otro arreglo
 int A[3][3];
 A[3] es un arreglo de tres elementos
 Cada elemento es otro arreglo de 3 elementos enteros

int A[3][3];
(0,0) (0,1) (0,2) A[0] A[0][0] A[0]1] A[0][2]

(1,0) (1,1) (1,2) A[1] A[1][0] A[1][1] A[1][2]

(2,0) (2,1) (2,2) A[2] A[2][0] A[2][1] A[2][2]


ESTRUCTURAS o REGISTROS
 Es un grupo de “componentes”. Cada componente
 Tiene su propio identificador, y
 Se conoce como “elemento” o “campo” de la estructura
 Ejemplo: typedef struct TNombreCompleto{
char Primero[10];
char Inicial;
char Ultimo[10];
}NombreCompleto;

 Es la declaración del nuevo “tipo de dato”: NombreCompleto


 Con este tipo de dato, podremos crear “variables”:
NombreCompleto snombre, enombre;
USANDO ESTRUCTURAS
 snombre es una variable de tipo NombreCompleto
 Tiene la misma forma que la del nuevo tipo de dato
 Cada miembro/campo ocupa memoria
 Para acceder a un campo, se indica,
 La variable seguida de un punto y del nombre del campo. Ejemplo
snombre.Inicial = ‘L’;
Los registros de tipo
NombreCompleto, tendrán la snombre
misma “estructura” primero inicial
Cada dato tiene diferente
tamaño y espacio en
memoria
ultimo
Cada dato representa una
información diferente
AMBITO DE VARIABLES
 Los parámetros y variables, dentro de una función,
 Son variables con ámbito local
 Solo son validas en ese ambiente,
 Las variables también pueden tener un ámbito “global”
 Empiezan a existir desde su declaración, y
 Son liberadas con el alcance de un archivo: variables externas
 Para darle privacidad a una variable
 Para que no pueda ser vista por otros archivos,
 Se la declara static, con ámbito global para archivo únicamente
Lectura de caracteres
scanf (stdio.h) utilizando el formato %c. requiere presionar ENTER
getch (conio.h) no requiere de ENTER.
getchar (stdio.h) requiere presionar ENTER

#include <stdio.h>
#include <conio.h>
printf("\n");
main(){
printf("\ningrese otro caracter: ");
char p1,p2,p3=65;
scanf("%c",&p2);
printf("\ningrese un caracter: ");
printf("%c",p2);
p1 = getchar();
printf("\ningrese otro caracter: ");
putchar(p1);
p2 = getch();
printf("\n");
printf("caracter leido: %c",p2);
printf("\nel caracteer p3 es:");
getch();
putchar(p3);
}
Uso de fflush
Se requiere borrar el buffer para leer correctamente

#include <stdio.h>
#include <conio.h>
printf("\ningrese otro caracter: ");
main(){
scanf("%c",&p2);
char p1,p2,p3=65;
printf("%c",p2);
printf("\ningrese un caracter: ");
printf("\ningrese otro caracter: ");
p1 = getchar();
fflush(stdin);
putchar(p1);
p2 = getch();
printf("\n");
fflush(stdin);
fflush(stdin);
printf("caracter leido: %c",p2);
printf("\nel caracteer p3 es:");
getch();
putchar(p3);
}
printf("\n");
Apuntadores
Una variable de tipo apuntador contiene una dirección de memoria.
La dirección de memoria señalada por el apuntador es la que contiene el
dato que puede ser de cualquier tipo, incluso void.
entero
Asigna la dirección de entero a
pentero 548
int entero, *pentero;
pentero entero
entero = 548;
pentero = &entero; 548
*pentero = -234;

pentero entero
NOTA: a los apuntadores solo
puede asignárseles: 0, NULL o -234
una dirección
Ejemplo
#include <stdio.h>
#include <conio.h>

main(){
int entero,*pentero;
entero = 548;
pentero = &entero;
printf("La dirección de entero es %d\n",&entero);
printf("el valor de pentero es %d\n",pentero);
printf("el valor de entero es %d\n",entero);
printf("el valor de *pentero es %d\n",*pentero);
*pentero = -234;
printf("el valor de entero es %d\n",entero);
printf("el valor de *pentero es %d\n",*pentero);
getch();
}
Aritmética de apuntadores
Los apuntadores pueden utilizarse para acceder a los elementos de un arreglo.

#include <stdio.h>
#include <conio.h>

main(){
int a[10]={3,4,1,8,2,3,4,5,7,0},*b;
b = a;//b apunta al inicio del arreglo a
printf("dirección de b es %d, el contenido es %d\n",b,*b);
b = b + 1;//b apunta a a[1]
printf("dirección de b es %d, el contenido es %d\n",b,*b);
b = b + 3;//b apunta a a[4]
printf("dirección de b es %d, el contenido es %d\n",b,*b);
b = b - 2;//b apunta a a[2]
printf("dirección de b es %d, el contenido es %d\n",b,*b);
getch();
}
#include <stdio.h>
#include <conio.h>

main(){
double a[10]={3,4,1,8,2,3,4,5,7,0},*b;
b = a;//b apunta al inicio del arreglo a
printf("dirección de b es %d, el contenido es %lf\n",b,*b);
b = b + 1;//b apunta a a[1]
printf("dirección de b es %d, el contenido es %lf\n",b,*b);
b = b + 3;//b apunta a a[4]
printf("dirección de b es %d, el contenido es %lf\n",b,*b);
b = b - 2;//b apunta a a[2]
printf("dirección de b es %d, el contenido es %lf\n",b,*b);
getch();
}
Apuntadores y subíndices
La aritmética de apuntadores y los subíndices son equivalentes.

#include <stdio.h>
#include <conio.h>

main(){
double a[10]={3,4,1,8,2,3,4,5,7,0},*b;
int i;
b = a;//b apunta al inicio del arreglo a
for(i=0;i<10;i++)
printf("a[%d]=%lf\n",i,a[i]);
for(i=0;i<10;i++)
printf("*(b+%d)=%lf\n",i,*(b+i));
getch();
}
Apuntadores a funciones
Las funciones se comportan como apuntadores.
El nombre de la función es un apuntador al inicio del código de la función.
Las funciones pueden pasarse como parámetros a otras funciones.
Ejemplo de apuntador a función
#include <stdio.h>
#include <conio.h>
#include <math.h>

void tabula(double a, double b,double (*fun)(double )){


double x,y;
for(x=a;x<=b;x+=(b-a)/10.0){
y = (*fun)(x);
printf("f(%lf) = %lf \n",x*180/3.1416,y);
}
}

main(){
tabula(0,3.1416/2,sin);
tabula(0,3.1416/2,cos);
getch();
}
Salida de apuntador a
funciónf(0.000000) = 0.000000
f(9.000000) = 0.156435
f(18.000000) = 0.309018
f(27.000000) = 0.453991
f(36.000000) = 0.587786
f(45.000000) = 0.707108
f(54.000000) = 0.809018
f(63.000000) = 0.891008
f(72.000000) = 0.951057
f(81.000000) = 0.987689
f(0.000000) = 1.000000
f(9.000000) = 0.987688
f(18.000000) = 0.951056
f(27.000000) = 0.891006
f(36.000000) = 0.809016
f(45.000000) = 0.707105
f(54.000000) = 0.587783
f(63.000000) = 0.453988
f(72.000000) = 0.309014
f(81.000000) = 0.156431
¿Que valores tienen las
variables?
int x. *px:
x *px y *py
float y, *py;
x = 5;
px = &x;
*px = 2*x + *px;
y = x;
py = &y;
y = *py + x;
cout<<" final *px = "<<*px <<" x = " <<x<<"\n";
cout<<" final *py = "<<*py <<" y = "<<y<<"\n";
Preguntas
UNIONES
 Permite que una variable se interprete de varias formas distintas,
dependiendo de la necesidad
 En una estructura
 Siempre es válido referirse a cualquier miembro de la misma
 Si hay n miembros, hay n cajones de memoria
 En una unión
 Solo trabajaremos con un miembro a la vez
 Hay un solo cajón de memoria, capaz de almacenar al mas grande de los
miembros
 Si el elemento escogido es mas pequeño, sobrara espacio
UNIONES
typedef enum {Entero, Real} Tdato;

typedef union ValorPolimorfico{


int valor_entero;
typedef union ValorPolimorfico{ float valor_real;
int valor_entero; Tdato tipo;
float valor_real; };
};
ValorPolimorfico a;
ValorPolimorfico a; printf(“Tipo de dato:”);
a.valor_entero = 9; a.tipo = GetInteger();
a.valor_real = 8.9; if a.tipo == Entero then
a.valor_entero = 9;
elseif a.tipo == Real then
a.valor_real = 8.9;

También podría gustarte