Hp03 Arreglos, Punteros..

Anuncio
CAPÍTULO 3
ARREGLOS, PUNTEROS Y ASIGNACIÓN DINÁMICA DE MEMORIA
Un arreglo, también llamado matriz (array), es un conjunto de elementos dispuestos secuencialmente, que
contienen datos del mismo tipo. El tamaño de un arreglo está dado por su número de elementos. El tamaño se debe
fijar cuando se declara el arreglo. El tamaño y el tipo de datos del arreglo definen el espacio de memoria que
ocupará dicha matriz. Estos arreglos pueden ser de uno o varias dimensiones. No existe límite, salvo la cantidad
de memoria existente en el computador.
3.1. DECLARACIÓN DE UN ARREGLO O MATRIZ
Su formato es el siguiente:
tipo ident_arreglo[num_elementos];
tipo ident_arreglo[num_fila][num_col];
Ej 3.1. Declaración de arreglo unidimensional y bidimensional
void()
{
void()
{
int tabla[10][2];
...
int mat[10];
...
}
}
En este caso se ha definido un arreglo de 10 elementos enteros. Los que ocupan 20 bytes de memoria. El
acceso de los elementos se hace desde el elemento 0 al elemento 9, es decir:
mat[0] mat[1]
.....
mat[9]
Acceso a los elementos de una matriz
Pueden ser accesado en forma individual o por medio de un índice, el cual debe ser entero. Para inicializar
un elemento en particular:
Ej 3.2. Diferentes formas de acceso de un arreglo.
void main()
{
int matriz[10];
matriz[3]=10;
matriz[9]=5;
....
}
void main()
{
int m[10];
m[3]=m[9]=4;
m[0]=0;
....
}
void main()
{
int m[5],i=3;
m[i]=3;
m[i*2-1]=65;
...
}
26
Preparado por Juan Ignacio Huircán
Ej 3.3. Utilizando un ciclo for para inicializar un arreglo:
void main()
{
int i, m[10];
for(i=0;i<10;i++) m[i]=0; /* pone en 0 todos los elementos del arreglo */
...
}
Ej 3.4. Declarando e inicializando un arreglo de 5 elementos.
void main()
{
int ma[5]={3,4,6,89,10};
....
}
Si se sobrepasan los límites del arreglo, el compilador NO entregará mensaje de error alguno. El acceso a
arreglo bidimensional se puede realizar de acuerdo a Ej 3.3.
Ej 3.5. Declaración e inicialización de una matríz de dos dimensiones.
void main()
{
int a[2][3]= {
{1,2,3},
{4,5,6}
};
}
En este caso es una matriz que tiene dos filas y tres columnas, donde:
a[0]: contiene la direccion de memoria de la primera fila
a[1]: contiene la dirección de memoria de la segunda fila.
a contiene la dirección de a[0].
Herramientas de Programación
27
Ej 3.6. El programa despliega el contenido de la matriz a[ ][ ] en pantalla.
#include<stdio.h>
void main()
{
int a[2][3]= {
{1,2,3},
{4,5,6}
};
int i, j;
for(i=0; i<2;i++)
for(j=0;j<3;j++) printf( "%d ", a[i][j]);
}
3.2. CADENAS DE CARACTERES
Las cadenas de caracteres (string) son arreglos que se componen de caracteres alfanuméricos. El final de
una cadena se indica con un caracter especial, éste es un byte compuesto por 8 ceros binarios, es decir 0x00.
Luego, el tamaño de la cadena debe ser lo suficientemente grande para contener dicho caracter inclusive. Una
cadena declarada como cad[10], podrá contener como máximo 9 caractéres.
El archivo de cabecera string.h proporciona una serie de funciones que permiten el manejo de cadenas
de caracteres. No existen operadores que permitan comparar cadenas o copiar una cadena en otra, por lo que se
debe hacer uso de las funciones definidas en string.h .
Ej 3.7. Tratamiento de cadenas.
#include<stdio.h>
#include<string.h>
void main()
{
char cad[10], buf[10];
strcpy(cad, "HOLA");
/* Copia en Cad la cadena "HOLA" */
strcpy(buf, cad);
/* Pasa el contenido de cad a buf */
if (!strcmp(buf,cad)) printf("SON IGUALES!");
}
La función strcpy es una contracción de la operación string copy. Al realizar dicha operación la
primera vez, el contenido de cad es el siguiente:
0x48 0x4f 0x4c 0x41 0x00 ??
H
O
L
A
??
??
??
??
La función strcmp permite comparar dos cadenas de caracteres. Esta comparación se realiza hasta el
caracter 0x00 de final de cadena. Es importante distinguir entre 'A' y "A", el primero es el caracter A que se
codifica en un byte (0x41) y el segundo es la cadena que contiene un caracter A y ocupa dos bytes. (0x41,
0x00).
28
Preparado por Juan Ignacio Huircán
Ej 3.8. Inicializando una matríz de caracteres.
void main()
{
char nombres[3][10]={
"IGNACIO",
"PEDRO",
"JUAN"
};
}
3.3. PUNTEROS Y ARREGLOS
También el acceso a los arreglos puede hacerse mediante punteros asignando un puntero al primer
elemento del arreglo.
Ej 3.9. Acceso de matrices mediante punteros.
void main()
{
char mat[10], *pmat, i;
mat[0]=10;mat[1]=30;mat[2]=50;mat[3]=60;
pmat=&mat[0];
pmat++;
i=*pmat;
i=*pmat +1;
i=*(pmat+1);
i=*++pmat;
i=++*pmat;
}
/* pmat apunta a mat[0] */
Las operaciones realizadas sobre mat son las siguientes:
pmat=&mat[0];
pmat++;
i=*pmat;
i=*pmat +1;
i=*(pmat+1);
i=*++pmat;
i=++*pmat;
pmat apunta a mat[0]
pmat apunta a mat[1]
i= 30
i= 31
i= 50, pmat apunta a mat[2]
se efectua ++pmat, es decir pmat apunta a mat[3], luego i=60
i=60, luego mat[2]= 61, se incrementa.
Herramientas de Programación
29
3.4. ASIGNACIÓN DINÁMICA DE MEMORIA.
Modelos de compilación
El compilador C permite el trabajo con diferentes modelos de compilación, es decir, las tres zonas que
forman parte de un programa en C, el código, los datos y la pila (stack), pueden tener diferentes tamaños.
Considerando la forma de direccionamiento en la familia 80x86, se han implementado diferentes modelos
de asignación de memoria para los computadores basados en dichos microprocesadores.
El modelo S (Small Model)
Para el caso del compilador TurboC, este es el modelo por defecto y es suficiente para la mayoría de las
aplicaciones. Las variables globales y estáticas no pueden ocupar más de 64Kbytes. Los punteros se codifican en
16 bits (near).
reserva
(farheap)
Limitado según
Mem disponible
SP
pila
zona
asignación dinámica
(heap)
DS, SS
Máx. 64Kb
variables globales
y estáticas
CODIGO
Máx. 64Kb
CS
Figura 3.1. Modelo small.
Para este modelo de compilación existen dos zonas de memoria, las cuales pueden ser utilizadas. La
primera se encuentra entre las variables globales y la pila (stack), se conoce con el nombre "heap" y puede ser
accesada utilizando punteros de tipo near, los cuales son codificados en16 bits. la otra zona se conoce como
farheap y debe ser accesada con punteros de tipo far, dicho puntero es codificado en 32 bits.
El modelo Tiny
Este modelo se utiliza cuando hay que limitar la cantidad de memoria que se dedica a un programa. El
código, los datos y la pila se encuentran restringidos a un máximo de 64Kbytes. Se usan sólo punteros near.
30
Preparado por Juan Ignacio Huircán
pila
SP
zona
asignación dinámica
Máx. 64Kb
variables globales
y estáticas
CS, DS, SS
CODIGO
Figura 3.2. Modelo Tiny.
El modelo Medium
El CODIGO puede alcanzar hasta 1 Mbyte, pero las variables estáticas y la pila quedan restringidas a un
máximo de 64Kbytes. Los punteros del codigo son de tipo far y los de datos son de tipo near.
(farheap)
SP
Limitado según
Mem disponible
pila
zona
asignación dinámica
Máx. 64Kb
variables globales
DS, SS
y estáticas
CODIGO
Máx. 1Mb
CS
Figura 3.3. Modelo small.
El modelo Compact
El CÓDIGO está limitado a 64 Kbytes, pero los datos pueden extenderse hasta 1Mbyte, esto implica que
punteros far deben ser usados para los datos.
El modelo Large
Tanto el CODIGO como las variables pueden extenderse hasta 1 Mbyte. Todos los punteros se codifican
en 32 bits (far).
El modelo Huge
Son usados punteros tipo far tanto para el código como para los datos.
Herramientas de Programación
31
heap
Limitado según
Mem disponible
SP
pila
variables globales
DS
CS
y estáticas
CODIGO
Máx. 1Mb
Máx. 1Mb
Figura 3.4. Modelo huge.
Utilizando memoria dinámica
La asignación dinámica de memoria nos permite la utilización y definición de variables las cuales exceden
el máximo permitido por los modelos de compilación.
Existen diferentes funciones las que están definidas en alloc.h y mem.h.
Ej 3.10. Reservando memoria dinámica
#include<alloc.h>
#include<conio.h>
#include<stdio.h>
float datos[10000];
long sizemem=0;
char *p;
/* puntero near */
void main()
{
int i;
sizemem=coreleft();
/* Verifica mem disponible */
printf("%lu ",sizemem);
if(sizemem>20000)
{
p=(char *)malloc(20000);
for(i=0;i<20000;i++) *(p+i)=0x00; /* rellena con 0x00 la zona
reservada */
getch();
sizemem=coreleft();
printf("%lu ",sizemem);
getch();
free(p);
/* Libera memoria reservada */
sizemem=coreleft();
printf("%lu ",sizemem);
} else printf("NO EXISTE Memoria Suficiente\n");
}
32
Preparado por Juan Ignacio Huircán
Ej 3.11.Reservando memoria dinámica en la zona "farheap"
/* Este programa se debe ejecutar fuera de editor del Turbo C */
#include<alloc.h>
#include<conio.h>
#include<stdio.h>
float datos[10000];
long sizemem=0;
char far *p;
/* Puntero far */
void main()
{
long i;
sizemem=farcoreleft();
/* Verifica memoria en zona farheap */
printf("%lu ",sizemem);
if(sizemem>100000)
{
p=(char far *)farmalloc(100000);
/* Reserva 100000 bytes */
for(i=0;i<100000;i++) *(p+i)=0x00;
getch();
sizemem=farcoreleft();
printf("%lu ",sizemem);
getch();
farfree(p);
sizemem=farcoreleft();
printf("%lu ",sizemem);
}
else
{
printf("No queda Memoria disponible \n");
getch();
}
}
En estos programas se han utilizado algunas funciones definidas en alloc.h. Las funciones
farcoreleft() y coreleft( ), determinan cuanta memoria disponible existe tanto en el área far como en el
área near.
Descargar