|
ARRAYS DE ESTRUCTURAS
Cuando hablamos de arrays dijimos que se podían
agrupar , para formarlos , cualquier tipo de variables , esto es extensible a las
estructuras y podemos entonces agruparlas ordenadamente , como elementos de un array .
Veamos un ejemplo :
typedef struct {
char material[50] ;
int existencia ;
double costo_unitario ;
} Item ;
Item stock[100] ;
Hemos definido aquí un array de 100 elementos ,
donde cada uno de ellos es una estructura del tipo Item compuesta por tres variables , un
int , un double y un string ó array de 50 caracteres.
Los arrays de estructuras pueden inicializarse de
la manera habitual , así en una definición de stock, podríamos haber escrito:
Item stock1[100] = {
"tornillos" , 120 , .15 ,
"tuercas"
, 200 , .09 ,
"arandelas" , 90 , .01
} ;
Item stock2[] = {
{
'i','t','e','m','1','\0' } , 10 , 1.5 ,
{
'i','t','e','m','2','\0' } , 20 , 1.0 ,
{
'i','t','e','m','3','\0' } , 60 , 2.5 ,
{
'i','t','e','m','4','\0' } , 40 , 4.6 ,
{
'i','t','e','m','5','\0' } , 10 , 1.2 ,
} ;
Analicemos un poco las diferencias entre la dos
inicializaciones dadas , en la primera , el array material[] es inicializado como un
string , por medio de las comillas y luego en forma ordenada , se van inicializando cada
uno de los miembros de los elementos del array stock1[] , en la segunda se ha preferido
dar valores individuales a cada uno de los elementos del array material , por lo que es
necesario encerrarlos entre llaves .
Sin embargo hay una diferencia mucho mayor entre las
dos sentencias , en la primera explicitamos el tamaño del array , [100] , y sólo
inicializamos los tres primeros elementos , los restantes quedarán cargados de basura si
la definición es local a alguna función , ó de cero si es global , pero de cualquier
manera están alojados en la memoria , en cambio en la segunda dejamos implícito el
número de elementos , por lo que será el compilador el que calcule la cantidad de ellos
, basandose en cuantos se han inicializado , por lo tanto este array sólo tendrá
ubicados en memoria cuatro elementos , sin posibilidad de agregar nuevos datos
posteriomente .
Veremos más adelante que en muchos casos es usual
realizar un alojamiento dinámico de las estructuras en la memoria , en razón de ello , y
para evitar ademas el saturación de stack por el pasaje ó retorno desde funciones , es
necesario conocer el tamaño , ó espacio en bytes ocupados por ella .
Podemos aplicar el operador sizeof , de la siguiente
manera :
longitud_base_de_datos = sizeof( stock1 ) ;
longitud_de_dato = sizeof( Item ) ;
cantidad_de_datos = sizeof( stock1 ) / sizeof(
Item ) ;
Con la primera calculamos el tamaño necesario de
memoria para albergar a todos datos, en la segunda la longitud de un sólo elemento (
record ) y por supuesto dividiendo ambas , se obtiene la cantidad de records.
UNIONES
Las uniones son a primera vista, entidades muy
similares a las estructuras, están formadas por un número cualquiera de miembros, al
igual que aquellas, pero en éste caso no existen simultaneamente todos los miembros, y
sólo uno de ellos tendrá un valor válido.
Supongamos por caso, que queremos guardar datos para
un stock de materiales , pero los mismos pueden ser identificados , en un caso con el
número de articulo (un entero ) y en otro por su nombre ( un string de 10 letras como
máximo ). No tendría sentido definir dos variables , un int y un string , para cada
artículo , ya que voy a usar una modalidad ú la otra, pero nó las dos simultaneamente.
Las uniones resuelven este caso , ya que si declaro una que contenga dos miembros, un
entero y un string , sólo se reservará lugar para el mayor de ellos , en estee caso, el
string , de tal forma que si asigno un valor a éste se llenará ese lugar de la memoria
con los caracteres correspondientes, pero si en cambio asigno un valor al miembro
declarado como int éste se guardará en los dos primeros bytes del MISMO lugar de
memoria. Por supuesto, en una unión, sólo uno de los miembros tendrá entonces un valor
correcto .
|