You are on page 1of 28

Captulo 12

Tipos de Datos Definidos por el


Usuario
Aparte de los tipos de datos predefinidos: enteros, flotantes y apuntador, C nos permite
crear algunos tipos de datos a partir de los tipos de datos predefinidos y de tipos de datos
previamente definidos. Esto nos permite una representacin ms natural del problema a
resolver. Uno de esos tipos de datos, el arreglo ya ha sido estudiado anteriormente. En
este tema se estudiarn tres tipos ms: las enumeraciones, las estructuras y las uniones.
Tambin se estudiar un mecanismo que posee C para establecer aliases para los tipos
de datos lo que permite simplificar la sintaxis de las declaraciones y ayuda a
autodocumentar los programas.

Declaracin typedef
La declaracin typedef de C nos permite establecer un alias para un tipo de dato
predefinido o previamente definido por el usuario. Una vez declarado, ese alias puede
utilizarse en declaraciones de objetos (variables y parmetros), casts, tipos de funciones,
etc. La sintaxis de la declaracin typedef es la siguiente:
typedef tipo alias;

Una declaracin typedef empieza con la palabra reservada typedef. tipo es el tipo de
datos al que le estamos estableciendo el sinnimo dado por alias. Por ejemplo:
typedef unsigned char uchar;
typedef unsigned long ulong;
typedef int contador;

Estas declaraciones establecen a uchar, ulong y a contador como aliases de


unsigned char, unsigned long e int, respectivamente. En declaraciones typedef
ms complicadas es conveniente visualizar la parte de la declaracin:
tipo alias

como una declaracin de una variable, en la que alias ocupa la parte en la que ira el
nombre de la variable a declarar. Por ejemplo:

ITSON

Manuel Domitsu Kono

236

Tipos de Datos Definidos por el Usuario


typedef char *cadena;
typedef char mensaje[80];

Aqu hacemos que cadena sea un alias de char *, esto es, de apuntador a char y
mensaje sea un alias de char ... [80], esto es, una cadena de 80 caracteres. Ms
adelante veremos que la declaracin typedef puede emplearse con tipos declarados por
el usuario.
Hay varias razones para desear establecer aliases para los tipos de datos:

Simplifica las declaraciones de objetos. Por ejemplo es ms sencillo escribir


uchar x, y;
ulong z, w;

que
unsigned char x, y;
unsigned long z, w;

Hacen ms claro el propsito de ciertos objetos, esto es, autodocumentan un


programa. Por ejemplo:
contador i;
char buscaMayuscula(cadena s);

Alcance Lxico de una Declaracin typedef


Las declaraciones typedef pueden hacerse al principio de un bloque o externas a las
funciones por lo que sus alcances lxicos son de bloque y de archivo respectivamente.

Enumeraciones
Hay ocasiones en que usamos variables enteras para representar valores que no son
necesariamente numricos. Por ejemplo para almacenar los valores Booleanos de falso y
verdadero, el lenguaje C, emplea una variable entera donde 0 representa el valor de falso
y 1 representa el valor de verdadero. Como un segundo ejemplo, para representar los
meses del ao podemos emplear una variable entera codificando cada mes con un
nmero entero: 1 para Enero, 2 para Febrero, .. , 12 para Diciembre. Los inconvenientes
de codificar valores no numricos como nmeros son: tener que recordar la codificacin
empleada y el hecho de que en el programa no resulta tan obvio el significado de dichos
nmeros. En estos casos C nos permite definir tipos enumerados. Un tipo enumerado
nos permite asignarles un identificador a cada valor de un subconjunto finito del tipo entero
y de declarar variables que tomen valores de ese subconjunto. El conjunto de valores se
conoce como constantes de enumeracin.

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

237

Definicin de Tipos Enumerados


La definicin de un tipo enumerado establece una plantilla, es decir la forma, para una
variable del tipo enumerado que se est definiendo. La definicin del tipo no crea la
variable. La sintaxis de la definicin de un tipo enumerado es:
enum [rtulo] {
nomCte1 [= cte1][,
nomCte2 [= cte2]]...
}[nomVar1][, nomVar2]...;

enum es una palabra reservada con que empieza la definicin de un tipo enumerado.
rtulo es un identificador que sirve para referenciar al tipo que se est definiendo en las
declaraciones de objetos, casts y tipos de funcin. La referencia al tipo enumerado que se
est creando es enum rtulo y no slo rtulo.
nomCte1 = cte1, nomCte2 = cte2... es una lista de identificadores y las
constantes enteras que representan. Los identificadores de las constantes de
enumeracin deben ser diferentes entre s y diferentes de los nombres de las variables en
su mismo mbito. Si se omite el valor para el primer identificador ste toma el valor de 0.
Si se omite el valor de alguno de los otros identificadores ste toma el valor del
identificador anterior ms uno. Los valores asociados a cada identificador no tienen que
ser diferentes entre s ni aparecer en algn orden.
Al mismo tiempo que definimos un tipo enumerado podemos declarar variables de ese
tipo. nomVar1, nomVar2 ... son los identificadores de esas variables. Por ejemplo:
enum boolean {
FALSE, TRUE
};
enum mes {
ENE, FEB, MAR, ABR, MAY, JUN, JUL, AGO, SEP, OCT, NOV, DIC
} mes;
enum {
DOM, LUN, MAR, MIE = 1, JUE, VIE = 1, SAB = 0
} dia;

En este caso estamos definiendo tres tipos enumerados: enum boolean, enum mes y un
tercero que no tiene rtulo (cuando en una definicin de un tipo omitimos el rtulo, se dice
que es una definicin annima). La definicin del tipo enum boolean le asigna al
subconjunto de los enteros {0, 1} los identificadores FALSE y TRUE, respectivamente,
mientras que la definicin del tipo enum mes le asigna al subconjunto de los enteros {0, 1,
..., 11} los identificadores ENE, FEB, ..., DIC. En la segunda definicin, tambin se
est declarando la variable mes como del tipo enum mes. En la tercera definicin, se
establece que la variable eDia puede tomar los valores: DOM, LUN, MAR, MIE, JUE,

ITSON

Manuel Domitsu Kono

238

Tipos de Datos Definidos por el Usuario

VIE, SAB. Los identificadores DOM y SAB tienen el valor de 0, LUN, Mie y VIE tienen el
valor de 1 y MAR y JUE el valor de 2.
Podemos establecer un alias para un tipo enumerado. Por ejemplo:
typedef enum boolean eBoolean;

hace de boolean un alias de enum boolean, suponiendo que la enumeracin enum


boolean ya ha sido declarada. Se puede declarar un tipo enumerado y darle un alias al
mismo tiempo:
typedef enum boolean {
FALSE, TRUE
} eBoolean;

Sin embargo, como el propsito de crear un alias para un tipo es el de usarlo en lugar del
tipo original. Usaremos BOOLEAN como especificador de tipo ms que enum boolean y
por lo tanto el rtulo boolean no ser empleado. Por lo tanto la definicin anterior puede
escribirse como:
typedef enum {
FALSE, TRUE
} eBoolean;

Declaracin de Variables Enumeradas


Hay tres formas de declarar variables de un tipo enumerado.

La primera forma es declararlas al mismo tiempo que se define el tipo. Esto ya se


ilustr al definir el tipo enumerado mes, al mismo tiempo que se declar la variable
eMes como de ese tipo.

La segunda forma de declarar variables de tipo enumerado es declararlas como de


un tipo enumerado previamente declarado. Por ejemplo:
enum boolean bandera;
enum mes mes1, mes2;

La primera declaracin puede substituirse por


eBoolean eBandera;

si previamente se estableci que eboolean es un alias de enum boolean.

ITSON

La tercera forma de declarar variables de tipo enumerado consiste en declarar las


variables como de un tipo enumerado annimo. Por ejemplo:

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

239

enum {
DOM, LUN, MAR, MIE = 1, JUE, VIE = 1, SAB = 0
} dia;

Esta forma de declaracin slo se recomienda usarse cuando la declaracin de


variables se hace en un solo punto del programa ya que no podemos declarar
posteriormente otras variables del mismo tipo usando la segunda forma de
declaracin.

Tipos Enumerados y Constantes Enteras


Un identificador de una constante de un tipo enumerado puede emplearse en expresiones
donde se requiere la constante entera que representa, an cuando no se haya declarado
una variable del tipo enumerado. De hecho una definicin de un tipo enumerado es una
forma alterna de definir constantes enteras. Por ejemplo:
enum mes {
ENE, FEB, MAR, ABR, MAY, JUN, JUL, AGO, SEP, OCT, NOV, DIC
};

La cual es equivalente a las siguientes declaraciones de constantes:


const
const
const
...
const

int ENE = 0;
int FEB = 1;
int MAR = 2;
int DIC = 11;

Declaracin de Parmetros, Tipos de Funcin y Casts


de Tipos Enumerados
La declaracin de parmetros, tipos de funciones y casts de tipos enumerados slo puede
hacerse con tipos previamente definidos. En estos casos, el tipo enumerado no puede ser
de tipo annimo. Por ejemplo las siguientes declaraciones no son vlidas:
enum {FALSE, TRUE} hayDatos(void);
float ventasMes(enum {ENE, FEB, MAR, ABR, MAY, JUN,
JUL, AGO, SEP, OCT, NOV, DIC} mes);

en su lugar debern definirse primero los tipos enumerados, como:


enum boolean {
FALSE, TRUE
};
enum mes {
ENE, FEB, MAR, ABR, MAY, JUN, JUL, AGO, SEP, OCT, NOV, DIC
};

ITSON

Manuel Domitsu Kono

240

Tipos de Datos Definidos por el Usuario

typedef enum {
FALSE, TRUE
} eBoolean;
typedef enum {
ENE, FEB, MAR, ABR, MAY, JUN, JUL, AGO, SEP, OCT, NOV, DIC
} eMes;

y luego emplearlos
enum boolean hayDatos(void);
float ventasMes(enum mes mes);

o
boolean hayDatos(void);
float ventasMes(eMes mes);

Uso de Enumeraciones
Una variable de un tipo enumerado no est limitada a tomar slo los valores de las
constantes de enumeracin. En realidad puede tomar cualquier valor en el rango de los
enteros. Sin embargo, lo normal es slo asignarles los valores de las constantes de
enumeracin. Por ejemplo en:
mes = ABR;

la variable eMes toma el valor de 3. Una variable de tipo enumerado puede utilizarse de la
misma forma en que se utiliza una variable entera. Puede usarse en expresiones, ciclos,
listas de argumentos de una funcin y an como parte de nuevos tipos. Por ejemplo las
siguientes expresiones son vlidas.
if(bandera) break;
for(mes = ENE; mes <= DIC; mes++)
ventasAnuales += ventasMes(mes);

Ejercicio sobre Enumeraciones


Suponga que usamos la siguiente definicin de tipo enumerado para representar los
meses del ao:
typedef enum {
ENE, FEB, MAR, ABR, MAY, JUN, JUL, AGO, SEP, OCT, NOV, DIC
} eMes;

Construya una funcin que reciba como parmetro un valor de tipo MESES que represente
el mes actual y que regrese el valor del mes siguiente. El prototipo de la funcin es el
siguiente:

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

241

eMes mesSiguiente(eMes mesActual);

Por ejemplo, en la siguiente llamada a la funcin:


eMes mesSig = mesSiguiente(MAR);

almacenar el valor de ABR en la variable mesSig.

Espacios de Nombre
Dentro de un mbito o alcance no podemos usar el mismo identificador para nombrar dos
o ms objetos y/o funciones. Se dice que los objetos y funciones pertenecen al mismo
espacio de nombre. El mismo identificador puede utilizarse para diferentes propsitos,
incluso dentro del mismo alcance, si los usos son en diferentes espacios de nombres. Hay
cuatro espacios de nombre:

Objetos, funciones, nombres typedef y constantes enumeradas.

Etiquetas.

Rtulos de estructuras, uniones y enumeraciones.

Miembros de cada estructura o unin individualmente, esto es, en diferentes


estructuras o uniones pueden emplearse los mismos nombres de miembros.

Por ejemplo en las declaraciones siguientes:


enum mes {
ENE, FEB, MAR, ABR, MAY, JUN, JUL, AGO, SEP, OCT, NOV, DIC
};
typedef enum mes mes;

podemos usar el identificador mes tanto para el rtulo de la enumeracin como para su
alias ya que pertenecen a diferentes espacios de nombre.

Alcance de una Declaracin de Tipo


Las declaraciones de tipos enumerados, estructuras y uniones al igual que las
declaraciones typedef tienen dos alcances: Alcance de bloque y alcance de archivo.

ITSON

Manuel Domitsu Kono

242

Tipos de Datos Definidos por el Usuario

Estructuras
Un arreglo es una lista de variables todas del mismo tipo. Una estructura tambin es una
lista de variables relacionadas pero a diferencia de un arreglo, stas pueden ser de
diferentes tipos. Algunos ejemplos de listas de variables relacionadas que pueden
almacenarse en una estructura son los datos de un alumno: matrcula, NIP, nombre,
carrera; los datos de un artculo en inventario: clave, nombre, cantidad, localizacin, etc.

Definicin de Tipos Estructuras


La definicin de un tipo estructura establece una plantilla, es decir la forma, para una
variable del tipo estructura que se est declarando. La definicin del tipo no crea la
variable. La sintaxis de la definicin de un tipo estructura es:
struct [rtulo] {
tipo1 nomMiembro11 [, nomMiembro12] ...;
[tipo2 nomMiembro21 [, nomMiembro22] ...;]
...
}[nomVar1][, nomVar2]...;

rtulo es un identificador que sirve para referenciar al tipo que se est declarando en las
declaraciones de objetos, casts y tipos de funcin. La referencia al tipo estructura que se
est creando es struct rtulo y no slo rtulo.
tipo1 es el tipo de las variables nomMiembro11, nomMiembro12 ..., tipo2 es el
tipo de las variables nomMiembro21, nomMiembro22 ..., etc. Esas variables son las
que forman la variable tipo estructura y son llamadas miembros de la estructura.
Al mismo tiempo que definimos un tipo estructura podemos declarar variables de ese tipo.
nomVar1, nomVar2 ... son los identificadores de esas variables.
Por ejemplo:
struct punto {
double x, y;
};

define a struct punto como un tipo estructura para almacenar las coordenadas de un
punto en el plano.
struct triangulo {
struct punto p1, p2, p3;
}

define a struct triangulo como un tipo estructura para almacenar las coordenadas
de los vrtices de un tringulo. Note que una estructura puede contener a otra estructura
como miembro. La siguiente definicin establece a struct alumno como un tipo

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

243

estructura con los datos de un alumno y al mismo tiempo declara a alumno como una
variable del tipo struct alumno.
struct alumno {
int matricula;
char *nip;
char *nombre;
char *carrera;
} alumno;

Podemos establecer un alias para un tipo estructura. Por ejemplo:


typedef struct punto sPunto;
typedef struct alumno sAlumno;

hacen de sPunto y sAlumno alias de struct punto y struct alumno,


respectivamente. Al igual que con los tipos enumerados tambin podemos declarar una
estructura y darle un alias simultneamente:
typedef struct alumno {
int matricula;
char *nip;
char *nombre;
char *carrera;
} sAlumno;

o
typedef struct {
int matricula;
char *nip;
char *nombre;
char *carrera;
} sAlumno;

Declaracin de Variables Tipo Estructura


Las variables tipo estructura pueden declararse de la misma forma en que se declaran las
variables de un tipo enumerado.

La primera forma es declararlas al mismo tiempo que se define el tipo. Por ejemplo
al definir el tipo struct alumno, se declar la variable alumno como de ese tipo.

La segunda forma de declarar variables de tipo estructura es declararlas como de


un tipo estructura previamente declarado. Por ejemplo:
struct alumno alumno;

o
sAlumno alumno;

ITSON

Manuel Domitsu Kono

244

Tipos de Datos Definidos por el Usuario

si consideramos que sAlumno es un alias de struct alumno;

La tercera forma de declarar variables de tipo estructura consiste en declarar las


variables como de un tipo estructura annimo. Por ejemplo:
struct {
double x, y;
} punto;

Al igual que con las enumeraciones, esta forma de declaracin solo se recomienda
usarse cuando la declaracin de variables se hace en un slo punto del programa
ya que no podemos declarar posteriormente otras variables del mismo tipo usando
la segunda forma de declaracin.

Inicializacin de Variables Tipo Estructura


Una variable tipo estructura puede inicializarse al mismo tiempo que se declara. Por
ejemplo:
sAlumno alumno = {12345, "BXPK", "Juan Perez", "IE"};

inicializa los miembros matricula, *nip, *nombre, *carrera a 12345, "BXPK",


"Juan Perez", "IE".
Si el nmero de inicializadores es menor que el nmero de miembros, el compilador
rellena la estructura con ceros si los campos son numricos y con apuntadores nulos si
son apuntadores.

Operaciones con una Estructura


Las nicas operaciones vlidas con estructuras son: acceder a los miembros de una
estructura, asignar una estructura a otra del mismo tipo, tomar la direccin de una
estructura, y calcular el tamao de una estructura.

Acceso a los Miembros de una Estructura


Para acceder a los miembros de una variable de tipo estructura se utiliza el operador de
miembro de estructura (.) llamado tambin operador punto. La sintaxis de este
operador es
nomVar.nomMiembro

nomMiembro es el nombre del miembro de la variable tipo estructura nomVar. La


expresin nomVar.nomMiembro es sintcticamente equivalente al nombre de una
variable del tipo del miembro accesado. Por ejemplo dadas las declaraciones:

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

245

sPunto punto;
sAlumno alumno;
char nombre[40] = "Juan Olivas";

sPunto.x nos da acceso al miembro x de la estructura sPunto y como x es un entero, la


expresin sPunto.x puede emplearse como se emplea el nombre de una variable
entera. Luego
punto.x = 10.5;

almacena en el miembro x1 de la estructura sMarco el valor de 10, mientras que


punto.x += 3.6;

lo incrementa en uno. sAlumno.nombre nos permite acceder al miembro nombre de


sAlumno. Como nombre es un apuntador a char, la expresin sAlumno.nombre es un
apuntador a char, por lo que
alumno.nombre = nombre;

almacena la direccin de la cadena nombre en el miembro nombre de la estructura


sAlumno. La expresin
puts(alumno.nombre);

desplegara en la pantalla la palabra "Juan Olivas", y


alumno.nombre[1] = 'o';

o
*(alumno.nombre + 1) = 'o';

hacen que el contenido de la cadena titulo sea " Joan Olivas ".

Asignacin de una Estructura a Otra


Una variable del tipo estructura puede asignarse a otra estructura del mismo tipo. Por
ejemplo
sAlumno alumno1, alumno2;
alumno1 = alumno2;

Cada uno de los miembros de la estructura sAlumno2 se copian, byte por byte, a la
estructura sAlumno1.

ITSON

Manuel Domitsu Kono

246

Tipos de Datos Definidos por el Usuario

Direccin de una Estructura y Apuntadores a una Estructura


La direccin de una estructura (la direccin del primer miembro) puede obtenerse
utilizando el operador de direccin (&). Tambin podemos declarar apuntadores a
estructuras. Por ejemplo:
sAlumno alumno1, alumno2, *pAlumno;
pAlumno = &alumno1;
alumno2 = *pAlumno;

La primera lnea declara a alumno1 y alumno2 como dos estructuras del tipo sAlumno y
a pAlumno como un apuntador a una estructura de tipo sAlumno.
La segunda lnea almacena en pAlumno la direccin de alumno1, mientras que la tercera
lnea asigna a la variable alumno2 la estructura que se encuentra en la direccin dada por
pAlumno. Las dos ltimas lneas equivalen a la lnea
alumno2 = alumno1;

En el ejemplo anterior vimos como podemos utilizar el operador de indireccin (*) para
accesar a una estructura de la cual tenemos su direccin. Tambin podemos accesar a los
miembros de esa estructura. Por ejemplo para accesar al miembro matricula de la
estructura apuntada por psAlumno escribimos
(*pAlumno).matricula

Note que debemos primero desreferenciar el apuntador para obtener la estructura ya que
el operador punto requiere del lado izquierdo una estructura. Tambin note que son
necesarios los parntesis ya que el operador punto tiene mayor precedencia que el
operador de indireccin. Para simplificar la sintaxis de la expresin anterior C posee un
operador que nos permite accesar a un miembro de una estructura de la cual tenemos su
direccin, el operador de apuntador a estructura llamado tambin operador flecha. El
operador flecha formado por el signo menos (-) y el signo mayor que (>) sin espacios
intermedios (->) tiene la siguiente sintaxis
nomApunVar -> nomMiembro

nomMiembro es el nombre del miembro de la variable tipo estructura cuya direccin est
dada por nomApunVar. La expresin anterior es sintcticamente equivalente al nombre de
una variable del tipo del miembro accesado. Luego para accesar al miembro matricula
de la estructura apuntada por psAlumno utilizando el operador flecha, escribimos
pAlumno->matricula

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

247

Tamao de una Estructura


El operador sizeof() nos da el tamao de un tipo u objeto. La sintaxis de este operador
es
sizeof({tipo|nomVar})

donde tipo es el especificador de un tipo predefinido o declarado por el usuario y


nomVar es el nombre de un objeto de cualquier tipo. El operador sizeof() nos da el
tamao en bytes de ocupado por un objeto del tipo tipo o de un objeto llamado nomVar.
El operador sizeof() es un operador de tiempo de compilacin. Esto es, el clculo del
tamao del objeto se efecta durante la compilacin. Por ejemplo, dadas las declaraciones
int x, y[10];

las siguientes expresiones


sizeof(int)
sizeof(x)

nos dan el tamao de la variable x, mientras que el tamao del arreglo y puede obtenerse
con la expresin:
sizeof(y)

El operador tambin puede aplicarse a estructuras. Por ejemplo:


sizeof(struct alumno)
sizeof(sAlumno)
sizeof(alumno)

// Tamao del tipo estructura


// Tamao del tipo estructura
// Tamao de la variable de tipo estructura

nos dan el tamao en bytes de la variable alumno, dadas las declaraciones de los
ejemplos anteriores.

Estructura Interna de una Estructura


Los miembros de una estructura se almacenan en memoria en el mismo orden en que son
definidos. Sin embargo no podemos asumir que los miembros de una estructura se
encuentren en localidades contiguas de memoria. Esto se debe a que algunos
compiladores fuerzan (siempre u opcionalmente) a que los diferentes miembros de la
estructura se almacenen en direcciones mltiples de 2 o 4. Esto a fin de hacer ms
eficiente el acceso a los miembros de la estructura. Esto hace que algunos compiladores
dejen huecos entre los miembros de una estructura, por lo tanto el tamao de una
estructura no necesariamente es igual a la suma de los tamaos de los miembros de dicha
estructura. Por esa razn si deseamos saber el tamao de una estructura debemos
emplear el operador sizeof().

ITSON

Manuel Domitsu Kono

248

Tipos de Datos Definidos por el Usuario

Estructuras y Funciones
Una funcin puede regresar por el mecanismo de return una estructura completa. Por
ejemplo la siguiente funcin inicializa una estructura de tipo sPunto a un par de valores
que recibe como argumentos.
sPunto punto(double x, double y)
{
sPunto p;
p.x = x;
return p;

p.y = y;

Una funcin tambin puede recibir como argumento una estructura. Por ejemplo la
siguiente funcin regresa la distancia entre dos puntos
#include <math.h>
double distancia(sPunto p1, sPunto p2)
{
return sqrt(pow((p2.x-p1.x),2) + pow((p2.y-p1.y),2);
}

Como ejemplo de llamadas a las funciones punto() y distancia() tenemos:


double d;
sPunto p1;
...
p1 = punto(4.0, 7.0);
d = distancia(p1, punto(8.0, 2.0));
...

Por ltimo una funcin puede recibir como argumento un apuntador a una estructura. Por
ejemplo, la siguiente funcin recibe la informacin necesaria para desplegar un alumno, en
una estructura del tipo sAlumno.
void despliegaAlumno(sAlumno *pAlumno)
{
printf("%d, %s, %s, %s", pAlumno -> matricula, pAlumno -> nip,
pAlumno -> nombre, pAlumno -> carrera);
}

Note que dado a que el parmetro pAlumno es un apuntador a una estructura de tipo
sAlumno, utilizamos el operador flecha para accesar a los miembros de la estructura
apuntada por pAlumno. La llamada a la funcin despliegaAlumno() tendra la forma
sAlumno alumno = {12345, "BXPK", "Juan Perez", "IE"};
...
despliegaAlumno(&alumno);
...

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

249

donde vemos que a la funcin despliegaAlumno() le pasamos la direccin de la


estructura alumno.
Una funcin que recibe como argumento un apuntador a una estructura puede hacer el
mismo trabajo que las funciones que regresan una estructura por el mecanismo de return
o que las que reciben como argumento una estructura. De hecho las funciones que
regresan una estructura o las que reciben una estructura tienen dos inconvenientes:
Primero deben reservar espacio para la estructura, ya sea como una variable local o como
un parmetro y segundo toma tiempo que la funcin regrese o enviarle a la funcin toda
una estructura. Por otro lado tienen la ventaja de que la sintaxis para accesar a los
miembros de la estructura es ms sencilla ya que no tenemos que manejar apuntadores.
En resumen si las estructuras son de unos cuantos bytes no importa mucho el mecanismo
que usemos para enviarle a una funcin o que la funcin nos regrese una estructura. Pero
si la estructura es grande es ms eficiente mandarle a la funcin un apuntador a la
estructura.

Arreglos de Estructuras
Ya vimos que un miembro de una estructura puede ser de cualquier tipo: enteros,
flotantes, enumerados, estructuras y como veremos posteriormente uniones. Por otro lado
podemos agrupar estructuras en arreglos. Por ejemplo
sPunto puntos[100];

declara un arreglo de estructuras del tipo sPunto. La siguiente pieza de cdigo muestra la
sintaxis para accesar a los miembros de una estructura que es un elemento de un arreglo:
...
puntos[1] = punto(4.0, 7.0);
puntos[2] = punto(8.0, 2.0);
printf("\La distancia entre los puntos ");
printf("(%.2f, %.2f) y ", puntos[1].x, puntos[1].y);
printf("(%.2f, %.2f) es ", puntos[2].x, puntos[2].y);
printf("%.2f", distancia(puntos[1], puntos[2]);
...

En este ejemplo puntos[1] y puntos[2] son los nombres de dos de las estructuras
que componen el arreglo puntos.

Ejemplos sobre Estructuras


Se desea implementar un programa que permita administrar el catlogo de alumnos de
una universidad. El catlogo se almacenar en un arreglo donde cada elemento contiene
los datos de un alumno: matrcula, NIP, nombre y carrera, en una estructura. Para manejar
los datos de un alumno se crear el mdulo alumno. En el archivo de cabecera
alumno.h se define la estructura empleada para almacenar los datos de cada alumno,

ITSON

Manuel Domitsu Kono

250

Tipos de Datos Definidos por el Usuario

as como la declaracin de las funciones que permiten inicializar los datos de un alumno y
crear una cadena con los datos de un alumno.
alumno.h
/*
* File:
alumno.h
* Author: mdomitsu
*
* Created on 11 de abril de 2010, 05:31 PM
*/
#ifndef _ALUMNOS_H
#define
_ALUMNOS_H
// Tamao de una cadena para los datos de un alumno
#define TAM_ALUMNO 80
typedef struct {
int matricula;
char nip[7];
char nombre[40];
char carrera[7];
} sAlumno;
void inicializaAlumno(sAlumno *pAlumno, int matricula, char *pNip,
char *pNombre, char *pCarrera);
char* alumnoACadena(char *pCadenaAlumno, sAlumno *pAlumno);
#endif /* _ALUMNOS_H */

El archivo fuente alumno.c contiene las definiciones de las funciones declaradas en


alumno.h:
alumno.c
/*
* alumno.c
*
* Este mdulo representa a un alumno de una universidad
*/
#include <stdio.h>
#include "../includes/alumno.h"
/*
* Esta funcion inicializa los campos de una estructura de tipo sAlumno
* con los valores de sus parametros
*/
void inicializaAlumno(sAlumno *pAlumno, int matricula, char *pNip,
char *pNombre, char *pCarrera) {
pAlumno->matricula = matricula;
strcpy(pAlumno->nip, pNip);
strcpy(pAlumno->nombre, pNombre);
strcpy(pAlumno->carrera, pCarrera);
}
/*
* La funcin despliega los valores de los campos del alumno del parametro
* en un renglon.
*/

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

251

char* alumnoACadena(char *pCadenaAlumno, sAlumno *pAlumno) {


sprintf(pCadenaAlumno, "%d, %s, %s, %s", pAlumno->matricula,
pAlumno->nip, pAlumno->nombre, pAlumno->carrera);
return pCadenaAlumno;
}

Para implementar las operaciones que permitan agregar un alumno al catlogo de


alumnos, actualizar, eliminar y listar alumnos del catlogo de alumnos se implementar el
mdulo alumnos. En el archivo de cabecera alumnos.h se definen las operaciones:
alumnos.h
/*
* File:
alumnos.h
* Author: mdomitsu
*
* Created on 25 de abril de 2010, 06:58 PM
*/
#ifndef _ALUMNOS_H
#define
_ALUMNOS_H
typedef enum {
REPETIDO = -3, CATALOGO_LLENO, NO_EXISTE, OK
} eCodigoError;
int indiceAlumno(int matricula);
int obtenAlumno(sAlumno *pAlumno, int matricula);
int agregaAlumno(sAlumno *pAlumno);
int actualizaAlumno(sAlumno *pAlumno);
int eliminaAlumno(int matricula);
void despliegaAlumnos();
#endif /* _ALUMNOS_H */

El siguiente cdigo es un listado parcial del archivo alumnos.c con la declaracin del
arreglo para almacenar el catlogo de alumnos y los mtodos: indiceAlumno() y
despliegaAlumnos().
alumnos.c
/*
* alumnos.c
*
* Este mdulo representa las operaciones del catalogo de
* alumnos de una universidad
*/
#include <stdio.h>
#include "../../alumno/includes/alumno.h"
#include "../includes/alumnos.h"
static sAlumno alumnos[100];
static const int MAX_ALUM = 100;
static int numAlumnos = 0;
/*
* Esta funcin busca a un alumno en el catlogo de alumnos cuya
* matricula coincida con la matricula del parmetro. Regresa el

ITSON

Manuel Domitsu Kono

252

Tipos de Datos Definidos por el Usuario

* ndice del alumno en el arreglo si existe, NO_EXISTE en caso


* contrario.
*/
int indiceAlumno(int matricula) {
int i;
for(i =0; i < numAlumnos; i++) {
if(alumnos[i].matricula == matricula)
return i;
}
return NO_EXISTE;
}
...
/*
* La funcin despliega los valores de los campos de los alumnos del catalogo
* de alumnos. Uno por renglon.
*/
void despliegaAlumnos() {
int i;
char cadenaAlumno[TAM_ALUMNO];
for(i =0; i < numAlumnos; i++) {
printf("\n%s", alumnoACadena(cadenaAlumno, &alumnos[i]));
}
printf("\n");
}

Ejercicios sobre Estructuras


1. Implemente la funcin
int agregaAlumno(sAlumno *pAlumno);

que agrega al alumno del parmetro, al catlogo de alumnos. Si hay xito la funcin
regresa el valor OK. Si no hay espacio en el catlogo, la funcin regresa el valor de
CATALOGO_LLENO. Si el alumno ya est en el catlogo, la funcin regresa el valor
REPETIDO.
2. Implemente la funcin
int eliminaAlumno(int matricula);

que borra los datos del alumno cuya matrcula est dado por el parmetro, del
catlogo de alumnos. Si hay xito la funcin regresa el valor OK. Si el alumno no
existe en el catlogo, la funcin regresa el valor NO_EXISTE.

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

253

Uniones
Al igual que las estructuras, una unin es un tipo definido por el usuario consistente de una
lista de variables relacionadas que pueden ser de diferente tipo. A diferencia de una
estructura, en la que cada uno de sus miembros ocupa su propio espacio de memoria, en
una unin todos los miembros de la unin comparten el mismo espacio de memoria. Por
ejemplo, considere las siguientes definiciones y declaraciones:
struct s {
int x;
long y;
double z;
}

union u {
int x;
long y;
double z;
}

struct s a;

union u b;

Las variables a y b apareceran en la memoria como


a

b
x

Podemos ver que en la unin los miembros x, y y z comparten el mismo espacio de


memoria y por lo tanto slo uno de ellos puede estar almacenado en la variable a la vez.
El tamao de una unin es del tamao del mayor de sus miembros. El lenguaje C no
provee un mecanismo que nos permita determinar cul de los miembros est almacenado
en la variable. Es responsabilidad del programador recordar cul de los miembros est
almacenado.

Definicin de Tipos Uniones


La definicin de un tipo unin, al igual que la de una estructura establece una plantilla, es
decir la forma, para una variable del tipo unin que se est declarando. La definicin del
tipo no crea la variable. La sintaxis de la definicin de un tipo unin es
union [rtulo]
{
tipo1 nomMiembro11 [, nomMiembro12] ...;
[tipo2 nomMiembro21 [, nomMiembro22] ...;] ...
}[nomVar1][, nomVar2]...;

rtulo es un identificador que sirve para referenciar al tipo que se est declarando en las
declaraciones objetos, casts y tipos de funcin. La referencia al tipo unin que se est
creando es union rtulo y no slo rtulo.

ITSON

Manuel Domitsu Kono

254

Tipos de Datos Definidos por el Usuario

tipo1 es el tipo de las variables nomMiembro11, nomMiembro12 ..., tipo2 es el tipo


de las variables nomMiembro21, nomMiembro22 ..., etc. Esas variables son las que
forman la variable tipo unin y son llamadas miembros de la unin.
Al mismo tiempo que definimos un tipo unin podemos declarar variables de ese tipo.
nomVar1, nomVar2 ... son los identificadores de esas variables.
Los miembros de una unin pueden ser de cualquier tipo ya sea predefinido o definido por
el usuario. Tambin una estructura puede contener uniones y podemos tener arreglos de
uniones. Tambin podemos establecer aliases para uniones con la declaracin typedef.
Por ejemplo el tipo unin del ejemplo anterior puede tener el alias
typedef union u u;

Declaracin e Inicializacin de Variables Tipo Unin


Las variables tipo unin pueden declararse de la misma forma en que se declaran las
variables de un tipo estructura.
Una variable tipo unin slo puede inicializarse a un valor del tipo del primero de sus
miembros. Por ejemplo, la variable b del tipo unin U del ejemplo anterior pudo haberse
declarado e inicializado como:
u b = 125;

pero no como:
u b = 789.56

Operaciones con una Unin


Las nicas operaciones vlidas con las uniones son las mismas operaciones con las
estructuras y tienen la misma sintaxis: accesar a los miembros de una unin, asignar una
unin a otra del mismo tipo, tomar la direccin de una unin, y calcular el tamao de una
unin.
Como ya se mencion anteriormente, es responsabilidad del programador recordar el tipo
del dato que se encuentra almacenado en una unin. Por ejemplo en el siguiente
segmento de cdigo
u b;
...
b.x = 125;
printf("ld", b.y);
...

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

255

la funcin printf() no despliega el valor de 125, sino un nmero largo cuyos dos bytes
menos significativos contienen la secuencia binaria equivalente a 125. Sin embargo no
siempre es un error asignarle a una unin un valor del tipo de uno de sus miembros y
extraerle un valor del tipo de otro de sus miembros. De hecho esta propiedad de las
uniones se emplear en un subtema ms adelante. Otra de las ventajas de las uniones es
la de que al compartir sus miembros el mismo espacio de memoria, son de menor tamao
que una estructura con los mismos miembros. Por supuesto la unin slo se puede
emplear si estamos seguros que slo un miembro va a ocupar la unin a la vez.

Ejemplos Sobre Uniones


Se desea implementar un programa que permita administrar el inventario de un
laboratorio. El inventario se almacenar en un arreglo donde cada elemento contiene los
datos de un producto: clave, nombre, tipo de producto (material o reactivo), cantidad (un
entero para los materiales o un flotante para los reactivos) y unidad, en una estructura.
Para manejar los datos de un producto se crear el mdulo producto. En el archivo de
cabecera producto.h se define la estructura empleada para almacenar los datos de
cada producto, as como la declaracin de las funciones que permiten inicializar los datos
de un producto y crear una cadena con los datos de un producto.
producto.h
/*
* File:
producto.h
* Author: mdomitsu
*
* Created on 25 de abril de 2010, 10:04 PM
*/
#ifndef _PRODUCTO_H
#define
_PRODUCTO_H
// Tamao de una cadena para los datos de un producto
#define TAM_PRODUCTO 100
typedef enum {
MATERIAL, REACTIVO
} eTipo;
typedef struct {
int clave;
char nombre[40];
eTipo tipo;
union {
int nCantidad;
float fCantidad;
} cantidad;
char unidad[2];
} sProducto;
void inicializaMaterial(sProducto *pProducto, int clave, char *nombre,
int nCantidad, char *unidad);
void inicializaReactivo(sProducto *pProducto, int clave, char *nombre,
float fCantidad, char *unidad);
char* productoACadena(char *pCadenaProducto, sProducto *pProducto);

ITSON

Manuel Domitsu Kono

256

Tipos de Datos Definidos por el Usuario

#endif /* _PRODUCTO_H */

El archivo fuente producto.c contiene las definiciones de las funciones declaradas en


producto.h:

producto.c
/*
* producto.c
*
* Este mdulo representa a un producto de un almacen
*/
#include <stdio.h>
#include <string.h>
#include "../includes/producto.h"
/*
* Esta funcion inicializa los campos de un material apuntado por sProducto
* con los valores de sus parametros
*/
void inicializaMaterial(sProducto *pProducto, int clave, char *nombre,
int nCantidad, char *unidad) {
pProducto->clave = clave;
strcpy(pProducto->nombre, nombre);
pProducto->tipo = MATERIAL;
pProducto->cantidad.nCantidad = nCantidad;
strcpy(pProducto->unidad, unidad);
}
/*
* Esta funcion inicializa los campos de un reactivo apuntado por sProducto
* con los valores de sus parametros
*/
void inicializaReactivo(sProducto *pProducto, int clave, char *nombre,
float fCantidad, char *unidad) {
pProducto->clave = clave;
strcpy(pProducto->nombre, nombre);
pProducto->tipo = REACTIVO;
pProducto->cantidad.fCantidad = fCantidad;
strcpy(pProducto->unidad, unidad);
}
/*
* La funcin despliega los valores de los campos del producto del parametro
* en un renglon.
*/
char* productoACadena(char *pCadenaProducto, sProducto *pProducto) {
if (pProducto->tipo == MATERIAL)
sprintf(pCadenaProducto, "%d, %s, Material, %d, %s",
pProducto->clave, pProducto->nombre,
pProducto->cantidad.nCantidad, pProducto->unidad);
else if (pProducto->tipo == REACTIVO)
sprintf(pCadenaProducto, "%d, %s, Reactivo, %.4f, %s",
pProducto->clave, pProducto->nombre,
pProducto->cantidad.fCantidad, pProducto->unidad);
return pCadenaProducto;
}

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

257

Para implementar las operaciones que permitan agregar un producto al inventario de


productos, actualizar, eliminar y listar productos del inventario de productos se
implementar el mdulo productos. En el archivo de cabecera productos.h se definen
las operaciones:
productos.h
/*
* File:
productos.h
* Author: mdomitsu
*
* Created on 25 de abril de 2010, 11:02 PM
*/
#ifndef _PRODUCTOS_H
#define
_PRODUCTOS_H
typedef enum {
PRODUCTO_INSUFICIENTE = -3, INVENTARIO_LLENO, NO_EXISTE, OK
} eCodigoError;
int indiceProducto(int clave);
int obtenProducto(sProducto *pProducto, int clave);
int agregaProducto(sProducto *pProducto);
int actualizaProducto(sProducto *pProducto);
int elimninaProducto(sProducto *pProducto);
void despliegaProductos();
#endif /* _PRODUCTOS_H */

Como un producto es o un material o un reactivo pero no ambos, la cantidad es o un


entero o un flotante pero no ambos, por lo que podemos utilizar un tipo union con un
campo entero y un campo flotante para la cantidad y as optimizar el espacio de memoria.
El siguiente cdigo es un listado parcial del archivo productos.c con la declaracin del
arreglo para almacenar el catlogo de alumnos y los mtodos: indiceProducto() y
despliegaProductos().
productos.c
/*
* productos.c
*
* Este mdulo representa a los productos de un almacen
*/
#include <stdio.h>
#include "../../producto/includes/producto.h"
#include "../includes/productos.h"
static sProducto productos[100];
static const int MAX_PROD = 100;
static int numProductos = 0;
/*
* Esta funcin busca a un producto en el inventario de productos cuya
* clave coincida con la clave del parmetro. Regresa el

ITSON

Manuel Domitsu Kono

258

Tipos de Datos Definidos por el Usuario

* ndice del producto en el arreglo si existe, NO_EXISTE en caso


* contrario.
*/
int indiceProducto(int clave) {
int i;
for (i = 0; i < numProductos; i++) {
if (productos[i].clave == clave)
return i;
}
return NO_EXISTE;
}
/*
* Esta funcin regresa el producto del inventario de productos cuya clave
* coincida con la clave del parmetro. El producto se regresa en la
* estructura apuntada por el parametro pProducto. Regresa el ndice del
* producto en el arreglo si existe, NO_EXISTE en caso contrario.
*/
int obtenProducto(sProducto *pProducto, int clave) {
int pos = indiceProducto(clave);
if (pos == NO_EXISTE) return NO_EXISTE;
*pProducto = productos[pos];
return OK;
}
/*
* La funcin despliega los valores
inventario
* de productos. Uno por renglon.
*/
void despliegaProductos() {
int i;

de

los

campos

de

los

productos

del

char cadenaProducto[TAM_PRODUCTO];
for(i =0; i < numProductos; i++)
printf("\n%s", productoACadena(cadenaProducto, &productos[i]));
printf("\n");
}

Ejercicio sobre Uniones


Implemente la funcin
int agregaProducto(sProducto *pProducto);

que agrega el producto apuntado por el parmetro al catalogo de productos si no existe. Si


existe, incrementa su cantidad en la cantidad del producto del parmetro. Si hay xito la
funcin regresa OK. Si no hay espacio en el arreglo, la funcin regresa
CATALOGO_LLENO.

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

259

Campos de Bits
Un miembro entero o entero sin signo de una estructura puede declararse como formado
por un nmero dado de bits. Tal miembro se denomina Campo de bits, y su nmero
asociado de bits se llama su ancho. La sintaxis para declarar un campo de bits es:
{int|unsigned} nomCampo: ancho;

El ancho de un campo de bits es un nmero entero no negativo, cuyo valor mximo


depende de la implementacin del compilador de C.
Los valores negativos en un campo de bits con signo se almacenan en su forma
complemento de dos. Los rangos permitidos para algunos campos dependiendo del
tamao de bits se muestran en la tabla 13-1.
Tabla 13-1. Rango de los campos de bits.
Tamao del campo
en bits

Con signo

Sin signo

-1 .. 0

0 .. 1

-2 .. 1

0 .. 3

-4 .. 3

0 .. 7

-8 .. 7

0 .. 15

-16 .. 15

0 .. 31

-32 .. 31

0 .. 63

-64 .. 63

0 .. 127

...

Normalmente los campos de bits se declaran como miembros consecutivos de una


estructura. El orden en que se acomodan los campos de bits depende de la
implementacin del compilador.
Por ejemplo, la siguiente declaracin:
struct BITS
{
int
unsigned
int
int
unsigned
} x;

i:
j:
:
k:
m:

2;
5;
4;
1;
4;

Crea una variable x de tipo estructura con la siguiente distribucin:

ITSON

Manuel Domitsu Kono

260

Tipos de Datos Definidos por el Usuario

15 14 13 12 11 10 9
m

Sin uso

0
i

La mayora de los compiladores no permiten que un campo de bits quede repartido entre
dos palabras. Por ejemplo la siguiente declaracin:
struct BITS2
{
int
a:
unsigned b:
int
c:
int
d:
unsigned e:
} y;

4;
5;
10;
1;
4;

Crea una variable y de tipo estructura en la cul los primeros dos campos quedan en una
palabra y los otros tres en otra.
Primer palabra
15 14 13 12 11 10 9 8 7 6

Segunda palabra
15 14 13 12 11 10 9 8 7 6 5
e

Podemos mezclar en una estructura, campos normales y campos de bits. Por ejemplo:
struct BITS3
{
long
char
int
unsigned
int
unsigned
};

x;
msj[20];
a: 4;
b: 5;
c: 10;
e: 4;

Restricciones en el Uso de los Campos de Bits


Las siguientes restricciones se aplican sobre los campos de bits
1. No se permite tomar la direccin de un campo de bits. Por ejemplo, sea bits una
variable del tipo estructura BITS definida anteriormente:
struct BITS bits

la siguiente expresin no es vlida:


&(bits.j)

ITSON

Manuel Domitsu Kono

Captulo 12

Tipos de Datos Definidos por el Usuario

261

2. No podemos crear arreglos de campos de bits. Por ejemplo:


struct BITS4
{
int
unsigned
int
unsigned
};

i: 3;
j: 5;
k[4]: 1;
m: 4;

/* No es vlido */

Ejercicio sobre Campos de Bits


Construya una funcin llamada codifica() que reciba tres parmetros enteros: a, b y c.
La funcin combinar los bits de los parmetros para formar un byte de la siguiente
manera:
c0

b2

b1

b0

a3

a2

a1

a0

la funcin regresa el byte codificado. La sintaxis de la funcin es:


unsigned char codifica(int a, int b, int c);

Problemas
1. Para el programa que permite administrar el catlogo de alumnos de una
universidad de los ejemplos sobre estructuras, implemente las siguientes funciones
en el mdulo alumnos:
int obtenAlumno(sAlumno *pAlumno, int matricula);

que regresa, en la variable apuntada por pAlumno, al alumno del catlogo de


alumnos cuya matrcula est dada por el parmetro matricula. Si hay xito la
funcin regresa el valor OK, en caso contrario regresa el valor NO_EXISTE.
int actualizaAlumno(sAlumno *pAlumno);

que actualiza los datos del alumno cuya matrcula est en el alumno del parmetro,
del catlogo de alumnos. Si hay xito la funcin regresa el valor OK. Si el alumno no
existe en el catlogo, la funcin regresa el valor NO_EXISTE.
2. Para el programa que permita administrar el inventario de un laboratorio de los
ejemplos sobre uniones, implemente las siguientes funciones:
int obtenProducto(sProducto *pProducto, int clave)

ITSON

Manuel Domitsu Kono

262

Tipos de Datos Definidos por el Usuario

que regresa el producto del catlogo de productos cuya clave coincida con la clave
del parmetro. El producto se regresa en la estructura apuntada por el parmetro
pProducto. Regresa el ndice del producto en el arreglo si existe, NO_EXISTE en
caso contrario.
int actualizaProducto(sProducto *pProducto)

que actualiza al producto del catalogo de productos cuya clave coincida con la
clave del producto del parmetro. Si hay xito la funcin regresa OK. Si el producto
no existe, la funcin regresa NO_EXISTE.
int elimninaProducto(sProducto *pProducto)

que reduce la cantidad del producto del catalogo de productos cuya clave coincida
con la clave del producto parmetro. Si despus de la reduccin la cantidad <= 0 el
producto se elimina del catalogo. Si hay xito la funcin regresa OK. Si el producto
no existe, la funcin regresa NO_EXISTE. Si la cantidad del producto en el
inventario para reducirla, la funcin regresa PRODUCTO_INSUFICIENTE.
3. Se requiere una funcin que reciba como parmetro un unsigned char y que
intercambie los bits 0 a 2 por los bits 4 a 6 sin alterar los bits 3 y 7. La funcin debe
regresar el valor del parmetro con los bits intercambiados. Utilice campos de bits
en la solucin. La sintaxis de la funcin es
unsigned char intercambia(unsigned char x);

4. Se requiere una funcin que realice la operacin contraria a la realizada por la


funcin codifica() del ejercicio sobre Campos de Bits. Esto es, debe extraer de
la variable x, los bits 0 a 3 y guardarlos en la variable apuntada por pA, los bits 4 a
6 y guardarlos en la variable apuntada por pB y el bit 7 y guardarlos en la variable
apuntada por pC. Utilice campos de bits en la solucin. La sintaxis de la funcin es
void decodifica(unsigned char x, int *pA, int *pB, int *pC);

ITSON

Manuel Domitsu Kono

You might also like