Está en la página 1de 17

Universidad Nacional de San Agustn

Escuela Profesional de Ingeniera de Sistemas


Compiladores
M.Sc. Percy Huertas Niqun

Proyecto Final: C
Generalidades
C es el lenguaje de programacin ideado por Kernighan y Ritchie. El lenguaje C
recibi este nombre por considerarse una evolucin del lenguaje B.
Este resumen presenta las principales caractersticas de C que hay que
implementar para el Proyecto de la asignatura de Compiladores. No es
necesario considerar los elementos de C no mencionados en este resumen.
Entre corchetes se dan indicaciones sobre la obligatoriedad u opcionalidad de
algunas partes del lenguaje. Con el fin de facilitar la implementacin del
compilador, las caractersticas mostradas en esta pgina pueden no coincidir al
100% con el estndar del lenguaje, por lo que, en caso de duda, se deber
implementar el comportamiento aqu descrito.
C es un lenguaje en el que se diferencian las minsculas y las maysculas (es
case sensitive). Tambin es un lenguaje de formato libre, es decir, que se
admiten espacios, tabuladores, saltos de lnea y comentarios en cualquier parte
del cdigo. Cada instruccin puede ocupar una o varias lneas. Las sentencias
y declaraciones terminan siempre en un punto y coma ( ;)
Las palabras clave que tiene el lenguaje son reservadas, aunque cada grupo
de alumnos slo ha de tener en cuenta las palabras asignadas a su grupo.
C es un lenguaje con estructura de bloques que se definen mediante la
utilizacin de las llaves { } y, por tanto, maneja los conceptos de nombres
globales y locales. Los nombres declarados fuera de cualquier funcin son
globales y pueden ser utilizados desde cualquier funcin. Los declarados en el
interior de una funcin son locales a dicha funcin.
En C es necesario declarar los identificadores antes de que se utilicen.
Adems, hay que implementar el Compilador de C considerando que es un
lenguaje con recursividad, por lo que cualquier funcin puede ser recursiva.
No se permite la definicin de funciones anidadas. El paso de parmetros es
por valor, salvo para cadenas y vectores, que es por referencia.

Estructura de un Programa
Para el Proyecto de Compiladores debe considerarse que un programa en C
estar compuesto por un nico fichero que ha de tener una serie de funciones,

siendo una de ellas la funcin principal. Adems, fuera de las funciones se


podrn declarar variables globales y tipos de datos.

Programa Principal
El programa principal (el que se ejecutar al arrancar el programa) ser una
funcin especial que recibe el nombre de main, que no puede llevar argumentos
y tiene que ser de tipo void:
void main (void)
{
implementacin_de_la_funcin_principal;
}

Comentarios
En C los comentarios se indican con los caracteres /* para abrir el comentario,
y con los caracteres */ para cerrarlo. No se admiten comentarios anidados. Los
comentarios pueden ocupar ms de una lnea y pueden ir colocados en
cualquier parte del cdigo donde pueda ir un espacio:
/* Comentario con apertura y cierre */

Constantes
El lenguaje dispone de varios tipos de constantes, de las cuales solamente
habr que tener en cuenta las siguientes:

Enteros
Las constantes enteras se escribirn en notacin decimal sin signo (por
ejemplo, 159, 0). El ensamblador que se utilizar dispone de nmeros enteros
de 2 bytes (con signo), por lo que el mximo entero ser el 32767.
El lenguaje tambin dispone de constantes enteras en notacin octal (usando
como prefijo un cero: 052) y en notacin hexadecimal (usando como prefijo un
cero y una equis: 0x1E4). [La implementacin de la notacin octal y hexadecimal
es opcional.]

Cadenas de Caracteres
Las constantes de cadena consisten en una secuencia de caracteres
encerrados entre comillas ("Hola, mundo!"). Las cadenas utilizan el carcter nulo
(cuyo cdigo ASCII es 0) como carcter de fin de cadena. Puede aparecer
cualquier carcter imprimible en la cadena. Para representar caracteres
especiales se utiliza una secuencia de escape, que comienza mediante el
carcter barra inversa y va seguido de un carcter. Algunos de estos caracteres
especiales son el salto de lnea ( \n), el tabulador (\t), el carcter nulo (\0), las
comillas dobles (\") o el carcter de barra inversa ( \\). Por ejemplo, la constante

representa a la cadena Hola, "Compiladores"!. [Esta


implementacin de las secuencias de escape es opcional.]
"Hola, \"Compiladores\"!"

Lgicas
En C no hay constantes lgicas propiamente dichas. Cualquier expresin que
se evale como 0 se considera como falso, y cualquier expresin que se evale
con un valor distinto a 0 se considera verdadera.

Operadores
Este lenguaje presenta un conjunto de operadores con los que escribir distintas
expresiones. Adems, se pueden utilizar los parntesis para agrupar
subexpresiones.

Operadores Aritmticos
Son los operadores que permiten realizar la suma, resta, producto, divisin y
mdulo: +, -, *, / y % [obligatorio implementar al menos uno]. Se aplican sobre
datos enteros, proporcionando un resultado entero.
Tambin existen los operadores ms y menos unarios: +, - [implementacin
opcional].

Operadores de Relacin
Son los operadores que permiten realizar las comparaciones de igual, distinto,
menor, mayor, menor o igual, mayor o igual: ==, !=, <, >, <= y >= [obligatorio
implementar todos los operadores]. Se aplican sobre datos enteros y
proporcionan un resultado lgico (0 si es falso, 1 si es verdadero).

Operadores Lgicos
Representan las operaciones de conjuncin, disyuncin y negacin: &&, || y !
[obligatorio implementar los operadores]. Se aplican sobre datos lgicos y
devuelven un resultado lgico (0 si es falso, 1 si es verdadero).

Operadores de Incremento y Decremento


Permiten auto-incrementar o auto-decrementar el valor de una variable entera:
++ y -- (pueden actuar como prefijos o como sufijos) [algunos grupos tienen que
implementar al menos uno de los cuatro]. Se aplican sobre variables enteras y
devuelven un resultado entero modificando tambin el valor de la variable.
Ejemplo:
a = j++; /* si j vala 5, ahora a == 5 y j == 6 */
a = ++j; /* si j vala 5, ahora a == 6 y j == 6 */

Operadores de asignacin

Permiten realizar asignaciones simples o realizando simultneamente una


operacin: =, +=, -=, *=, /= y %= [todos los grupos tienen que implementar la
asignacin simple (=) y algunos grupos debern implementar uno de los otros
operadores]. Ejemplo:
n += m;

/* es equivalente a n = n + m; */

Operador Condicional
Permiten obtener un valor basndose en una condicin: condicin ? exp1: exp2
[implementacin obligatoria]. Si la condicin es cierta, devuelve exp1, en caso
contrario, devuelve exp2. Ejemplo:
max = (a > b) ? a : b;

/* Si a > b entonces max == a, en otro caso, max == b */

Operador de Acceso a Campos de una Estructura


El operador punto permite utilizar los campos de un registro o estructura: .
Ejemplo:
reg.campo /* accede al campo de la estructura reg */

Operador de Acceso a Elementos de un Vector


El operador corchete permite utilizar los elementos de un vector: [ ]
[implementacin obligatoria]. Ejemplo:
a= v[i+1]; /* accede al elemento i+1 del vector v y copia su valor en a */

Precedencia de Operadores
En la tabla siguiente se muestra la precedencia de los operadores con el
siguiente significado: los operadores del mismo grupo tienen la misma
precedencia y, conforme se desciende por la tabla, la precedencia disminuye.
En cualquier caso, el uso de parntesis permite alterar el orden de evaluacin
de las expresiones [es obligatorio para todos los grupos implementar el uso de
parntesis y tener en cuenta las precedencias de sus operadores].
Precedencias de los Operadores
Operadores Significado
Asociatividad
Referencia
a
campo
de
estructura
.
()
Llamada
a
funcin Izquierda a derecha
[]
Referencia a elemento de vector
Negacin
lgica
!
Autoincremento
++
-Autodecremento
Derecha a izquierda
+
Ms
unario
Menos unario
*
Producto
Izquierda a derecha
/

Precedencias de los Operadores


Operadores Significado
Divisin
%
Mdulo
Suma
+
Resta
Mayor
>
Mayor o igual
>=
<
Menor
<=
Menor o igual
Igual
==
!=
Distinto
&&
Y lgico
||
O lgico
?:
Operador condicional
Asignacin simple
=
op=
Asignacin con operacin

Asociatividad

Izquierda a derecha

Izquierda a derecha

Izquierda a derecha
Izquierda a derecha
Izquierda a derecha
Derecha a izquierda
Derecha a izquierda

Identificadores
Los nombres de identificadores estn formados por cualquier cantidad de
letras, dgitos y subrayados ( _), siendo el primero siempre una letra o un
subrayado. Ejemplos: a, a3, A3, Sueldo_de_Trabajador, _9_9__...
Como ya se ha dicho, el lenguaje es dependiente de minsculas o maysculas,
por lo que los nombres a3 y A3 referencian a identificadores distintos.

Declaraciones
En el lenguaje C se exige la declaracin de variables antes de poder usarlas.
No se admite la redeclaracin de nombres en un mismo mbito. La declaracin
de variables se realiza fuera de las funciones (variables globales) o en las
funciones (variables locales).
Para realizar una declaracin de una variable, se escribe el nombre del tipo
seguido del nombre de la variable, finalizando en un punto y coma ( ;).
Se puede poner una lista de variables separadas por comas [esta declaracin
mltiple es opcional].
Tipo var0;
Tipo var1, var2, var3; /*se declaran tres variables*/

Opcionalmente, puede inicializarse una variable en la misma instruccin de la


declaracin, colocando detrs del nombre de la variable el operador de

asignacin (=) seguido de un valor constante [la inicializacin de variables es


opcional].
Tipo var0= valor0;
Tipo var1= valor1, var2, var3= valor3; /*se inicializan dos variables*/

Si una variable no se inicializa cuando se declara, tendr un valor indefinido


hasta que se le asigne un determinado valor (es decir, el compilador no realiza
una inicializacin por omisin).
Las declaraciones tendrn que estar siempre al principio de un bloque. Una vez
que se escribe una sentencia, ya no se pueden realizar declaraciones en dicho
bloque. Las declaraciones globales se realizan fuera de las funciones en
cualquier parte del cdigo, pero esas variables solo pueden utilizarse a partir de
dicha lnea.

Tipos de Datos
El lenguaje dispone de distintos tipos de datos, que pueden ser clasificados en
Tipos Bsicos (o elementales) y Tipos Compuestos (que se forman a partir de
tipos bsicos).

Tipos Bsicos
Se deben considerar slo los siguientes tipos de datos bsicos: entero, lgico y
vaco.
El tipo entero (que se representa con la palabra int) se refiere a un entero que
debe representarse con un tamao de 16 bits.
El tipo lgico (que no tiene representacin en C) permite representar valores
lgicos. Las expresiones relacionales y lgicas devuelven un valor lgico,
aunque no existen variables de tipo lgico. Cualquier tipo se puede usar con
dicho fin: al evaluarse como 0 se considera falso y, en caso contrario,
verdadero.
El tipo vaco (que se representa con la palabra void) indica la inexistencia de un
tipo propiamente dicho (se usa para funciones que no devuelven ningn valor y
cuando las funciones no reciben argumentos).
El lenguaje permite conversiones entre tipos: de entero a lgico y viceversa.
int dia, mes, fin;
fin= dia == 31 && mes == 12; /* el 31 de diciembre, fin valdr 1 (cierto) */

Tipos Compuestos
Cada grupo tendr que implementar uno de estos tipos compuestos,
basndose en la opcin que le corresponda. En los ejemplos se va a hacer uso
de elementos del lenguaje que se explicarn posteriormente.

Vectores
Para usar un vector es obligatorio declarar una variable de tipo vector. Su
declaracin es de la siguiente forma [implementacin obligatoria]:
int nombre_var [tamao];

El valor tamao debe ser un valor entero constante que especifica la dimensin
del vector. Los ndices del vector van desde 0 hasta tamao - 1, ambos incluidos.
Los elementos del vector son enteros [no hay que implementar vectores de
tipos compuestos].
Para acceder a un elemento del vector se usan los operadores corchete ( [ y ])
con el ndice en su interior. El ndice del vector puede ser cualquier expresin
entera vlida:
int v[31], w[31];
/* Se han declarado los vectores v y w de 31 elementos enteros */
/* Los ndices irn desde 0 hasta 30 */
int x[24];
/* Se ha declarado el vector x de 24 elementos enteros */
/* Los ndices irn desde 0 hasta 23 */
v[26]= 2;
/* se almacena un 2 en la posicin 26 */
x[3]= 13;
/* se almacena un 13 en la posicin 3 */
w[1]= v[x[3] * 2]; /* se almacena un 2 en la posicin 1 */

Con un vector se pueden realizar las siguientes operaciones: consultar sus


elementos (a travs de su ndice) y modificarlos, asignar una variable tipo
vector a otra (siempre que tengan la misma dimensin) y ser argumento de una
funcin.
La asignacin de vectores realiza una copia de todos los elementos de una
variable vector en otra variable vector.
Con respecto a las funciones, los vectores se pueden pasar como argumentos
por referencia (copiando su direccin), pero una funcin no puede devolver un
vector. En la declaracin de la funcin debe indicarse su tipo y su nombre
seguido de los corchetes, aunque no se indica la dimensin del vector:
void p (int z[], int y[], int x[])
/* declara el procedimiento p que recibe como parmetros por referencia tres vectores */
{
int a[31], i;
a= z; /* se realiza una copia de todo el vector z en a
for (i=8; i<20; i++)
x[i]= a[i - 1] + y [5 + i];
}

Cadenas
C dispone de una forma especfica para declarar cadenas basndose en el
tipo carcter: char *. La sintaxis para declarar o definir una variable cadena es
[implementacin obligatoria]:

char * variableCadena;

De esta manera se define una variable capaz de almacenar una cadena de


caracteres. Tambin puede inicializarse una variable cadena en la declaracin
[implementacin opcional]:
char * cadena_declarada;
char * cadena_inicializada= "Hola";

Se permiten operaciones de asignacin de cadenas (bien variables cadena,


bien asignar una constante cadena a una variable), envo como argumento a
una funcin por referencia (pero las funciones no pueden retornar una cadena),
impresin de una cadena en pantalla (mediante la funcin puts) y la lectura de
cadenas del teclado (mediante la funcin gets).
La asignacin de cadenas realiza una copia de todos los caracteres de una
variable cadena en otra variable cadena.
Con respecto a las funciones, las cadenas se pueden pasar como argumentos
por referencia (copiando su direccin), pero una funcin no puede devolver una
cadena. En la declaracin de la funcin debe indicarse su tipo, el asterisco y su
nombre:
char *u; /* variable global */
void copia (char * x, char * y)
{
char *aux;
gets (u); /* lee una cadena del teclado */
aux = u; /* copia la cadena u en aux */
puts (aux); /* imprime la cadena */
x= y;
/* copia la cadena y en x */
}
void pp (void)
{
char *s;
copia (s, "Mundo");
u= "Hola"; /* la variable u contendr la nueva cadena */
puts (u); /* escribe la cadena "Hola" */
puts (s); /* escribe la cadena "Mundo" */
}

[Nota: Como simplificacin para su implementacin, puede asumirse un tamao


fijo mximo para cada cadena.]
Estructuras
Una estructura representa un registro compuesto de un nmero fijo de
componentes, llamados campos, donde cada uno viene definido por su tipo y
su nombre. Para definir una estructura se usa la palabra reservada struct
[implementacin obligatoria]:
struct nombreRegistro
{
int campo1;

int campo2;
...
int campon;
};

Cada campo solo puede ser de tipo entero [no hay que implementar campos de
tipos compuestos]. Para usar una estructura hay que declarar primero el tipo
estructura y despus es necesario declarar una variable de dicho tipo para
acceder a los campos mediante el operador punto. El siguiente ejemplo
muestra la declaracin de una estructura y su uso:
struct Persona
{
int edad;
int mujer, jubilado;
int sueldo;
};
struct Persona yo;
yo.edad= 20;
yo.mujer= 0;
yo.jubilado= yo.edad > 65;
yo.sueldo= 300;

Las operaciones permitidas sobre estructuras son la asignacin de variables


del mismo tipo (declaradas como pertenecientes al mismo tipo de estructura, es
decir, que ambas tengan el mismo nmero de campos y el mismo nombre de
elementos), el acceso a los campos y su modificacin, y el envo como
parmetros por referencia a funciones.
La asignacin de estructuras realiza una copia de todos los campos de una
variable de tipo estructura en otra variable del mismo tipo estructura.
Con respecto a las funciones, las estructuras se pueden pasar como
argumentos por referencia (copiando su direccin), pero una funcin no puede
devolver una estructura. En la declaracin de la funcin debe indicarse la
palabra struct, su nombre de tipo y su nombre:
struct Persona yo, tu; /* declara las variables yo y tu de tipo Persona */
int R (void)
{
return tu.sueldo; /* accede al campo sueldo de tu */
}
void Q (struct Persona pp, struct Persona qq)
{
qq= pp;
qq.edad= getw ();
qq.sueldo= getw ();
qq.jubilado= qq.edad > 65;
if (qq.jubilado)
qq.sueldo= R() / 2;
}
void P (void)
{
yo.edad= 20; /* modifica el campo edad de yo */
yo.mujer= 0;
yo.jubilado= 0;

yo.sueldo= 300;
tu.mujer= !yo.mujer;
Q (yo, tu);
if (tu.mujer)
puts ("Hola, seora");
else
puts ("Hola, seor");
puts ("\nHas nacido en ");
putw (2007 - yo.edad);
if (!tu.jubilado)
{
puts ("Tu sueldo es "); putw (tu.sueldo);
puts (" euros al mes\n");
}
}

Instrucciones de Entrada/Salida
La funcin putw (expresin_entera) evala la expresin e imprime en pantalla su
resultado. Por ejemplo:
a= 50; putw (a * 2 + 16); /* imprime: 116 */

La funcin puts (cadena) imprime en pantalla la cadena. La cadena puede ser una
constante de tipo cadena [obligatorio para todos los grupos] o una variable de
tipo cadena [obligatorio para todos los grupos]. Por ejemplo:
a= "Adis"; puts ("Hola"); puts (a); /* imprime HolaAdis */

La funcin putl () imprime en pantalla un salto de lnea. Por ejemplo:


a=50; putw(a * 2 + 16); puts(" Euros"); putl(); /* imprime: 116 Euros y salta de lnea */

La funcin getw () lee un nmero entero del teclado y devuelve su valor. Por
ejemplo:
a= getw (); putw (a * a); /* imprime el cuadrado del nmero ledo */

La funcin gets (variable_cadena) lee una cadena del teclado, asignndose el valor
ledo a la variable recibida como parmetro [obligatoria para todos los grupos].
Por ejemplo:
gets (a); puts (a); /* imprime la cadena leda */

Sentencias
De todo el grupo de sentencias del lenguaje C, se han seleccionado para ser
implementadas en el Proyecto las que aparecen a continuacin [opcional u
obligatoriamente, segn se indique en cada caso]:

Sentencias de Asignacin

Existe una sentencia de asignacin en C, mediante el operador de asignacin


= [es obligatorio implementar la sentencia de asignacin]. Su sintaxis general
es la siguiente: identificador, igual y expresin: asigna al identificador el
resultado de evaluar la expresin (los datos deben ser de tipos compatibles):
i= 8 + 6;

Tambin se permite que a la izquierda de la asignacin aparezca un elemento


de un vector o un campo de una estructura.

Sentencia de Llamada a una Funcin


Esta sentencia permite invocar la ejecucin de una funcin previamente
definida [implementacin obligatoria].
La llamada a una funcin se realiza mediante el nombre de la funcin seguida
de los argumentos actuales (separados por comas) entre parntesis si existen
(si no tiene argumentos, hay que poner los parntesis):
p1 (5);
/* llamada a una funcin con un argumento entero */
p2 ();
/* llamada sin argumentos a una funcin */
p3 (b, i - 8); /* llamada con dos argumentos a una funcin

Los parmetros actuales en la llamada tienen que coincidir en nmero y tipo


con los parmetros formales de la declaracin de la funcin. Si la funcin
devuelve un valor, tambin podr incluirse una llamada a una funcin dentro de
cualquier expresin; si la llamada no se realiza en una expresin, el valor
devuelto se perder:
b= fun1 (9); /* llamada a una funcin con un argumento entero */
c= b + fun2 (b, fun3() - 8); /* llamada con dos argumentos a una funcin,
siendo fun3, una llamada a otra funcin sin argumentos */
fun2 (5, c); /* el valor devuelto por fun2 se pierde */

Sentencia de Retorno de una Funcin


C dispone de la sentencia return para finalizar la ejecucin de una funcin y
volver al punto desde el que fue llamada [implementacin obligatoria]. Si la
funcin es del tipo void, sta terminar cuando se ejecute la instruccin return o
al llegar al final del cuerpo de la funcin. Si la funcin no es de tipo void, sta
finalizar su ejecucin, devolviendo el valor obtenido al evaluar la expresin
que acompae a la sentencia return; en este caso, el tipo de la expresin de la
sentencia return debe coincidir con el tipo de la funcin.
SumaAlCuadrado (int a, int b) /*funcin entera*/
{
int j; /* variable local a SumaAlCuadrado */
j= a + b;
return j * j;
/* Como es una funcin entera, tiene que llevar una expresin entera. *
* La funcin finaliza y devuelve el valor de la expresin
*/
}

void pro (int x)


{
x= SumaAlCuadrado (x - 1, x);
/* x contendr el valor devuelto por la funcin: (x+x-1)^2 */
if (x > (194/2))
return; /* como es un procedimiento, no puede llevar expresin;
finaliza la ejecucin del procedimiento */
putw (SumaAlCuadrado (x, x));
} /* finaliza la ejecucin del procedimiento */

Sentencia Condicional
Selecciona la ejecucin de una de las secuencias de sentencias que encierra,
dependiendo del valor correspondiente de una condicin de tipo lgico. Tiene
dos formatos [implementacin obligatoria]:

if (condicin) sentencias1
if (condicin) sentencias1 else sentencias2

Si la condicin se evala como cierta (distinto de cero) se ejecutan las sentencias1;


en caso contrario, se ejecutan las sentencias2 (si el programador las ha escrito).
Cada uno de estos grupos de sentencias podr ser bien un bloque de
sentencias encerradas entre llaves o bien una nica sentencia:
if (a > b)
c= b;
else
{
c= a;
if (fin)
puts ("adis");
}

Sentencia Repetitiva

while

Esta sentencia permite repetir la ejecucin de unas sentencias basndose en el


resultado de una expresin lgica [implementacin obligatoria]. La sintaxis es:
while (condicin) sentencias.
Se evala la condicin y, si resulta ser cierta (distinta de 0), se ejecutan las
sentencias (que puede ser una nica sentencia o bien un bloque de sentencias
encerradas entre llaves). Este proceso se repite hasta que la condicin sea falsa
(se evale como 0):
while (n <= 10)
{
n= n + 1;
putw (n);
} /* mientras que n sea menor o igual que 10... */

Sentencia Repetitiva

do while

Esta sentencia permite repetir la ejecucin de las sentencias del bucle mientras
se cumpla una condicin [implementacin obligatoria para algunos grupos]. La
sintaxis es: do sentencias while (condicin);. En esta instruccin se puede colocar
una nica sentencia o bien un bloque de sentencias encerradas entre llaves.
Se ejecutan las sentencias de forma repetitiva; seguidamente se evala la
condicin y, si resulta ser cierta (distinto de 0), se ejecutan de nuevo las
sentencias. Este proceso se repite hasta que la condicin sea falsa (se evale
como 0):
do {a++; c *= b;} while (a < b);

Sentencia Repetitiva

for

Esta sentencia for permite ejecutar un bucle segn una condicin compleja
[implementacin obligatoria]. La sintaxis es: for (inicializacin; condicin; actualizacin)
sentencias. La inicializacin debe ser una sentencia de asignacin o nada; la
condicin debe ser una expresin lgica; y la actualizacin puede ser una
asignacin, un autoincremento o autodecremento [para los grupos que tengan
esta opcin] o estar vaca. Las sentencias pueden estar formadas por un
bloque delimitado por llaves o por una nica sentencia.
El funcionamiento de este bucle es como sigue:
1.
2.

Se ejecuta la inicializacin
Se evala la condicin

3.

Si la condicin es falsa (igual a 0), se abandona la ejecucin del bucle

4.

Se ejecutan las sentencias

5.

Se ejecuta la actualizacin

6.

Se vuelve al paso 2.

for (i = 1; i < 10; i++) f *= i;

Sentencia de Seleccin Mltiple


Esta sentencia selecciona una ejecucin de unas sentencias basndose en el
resultado de una expresin [implementacin obligatoria]. La sintaxis de la
sentencia de seleccin mltiple es:
switch (expresin)
{
case valor1: sentencias1
case valor2: sentencias2
/* . . . */
default: sentenciasn;
}

Su funcionamiento es como sigue: Se evala la expresin (que debe ser de tipo


entero), se busca el valor que coincida con el resultado (los valores tienen que
ser constantes enteras) y se ejecutan sus sentencias asociadas. Una vez
ejecutadas, se contina la ejecucin de todas las sentencias asociadas a todos
los valores que se encuentren a continuacin hasta el final del switch. Si no se
encuentra el valor, se ejecutan las sentencias asociadas a default, si el
programador la ha incluido. [El default es opcional para la implementacin.]:
switch (dia)
{
case 1: puts ("lunes");
case 2: puts ("martes");
case 3: puts ("mircoles");
case 4: puts ("jueves");
case 5: puts ("viernes");
default: puts ("fiesta");
} /* si dia == 4, se imprimir: jueves viernes fiesta */

Sentencia break
Esta sentencia aborta la ejecucin de un bucle o un switch [implementacin
obligatoria]:
switch (dia)
{
case 1: puts ("lunes"); break;
case 2: puts ("martes");
case 3: puts ("mircoles"); break;
case 4: puts ("jueves"); break;
case 5: puts ("viernes"); break;
default: puts ("fiesta");
} /* si dia == 4, se imprimir: jueves */

Funciones
Es necesario definir cada funcin antes de poder utilizarla. La definicin de una
funcin se realiza indicando el tipo, el nombre y, entre parntesis, los tipos y
nombres de los argumentos (si existen). Tras esta cabecera va un bloque
(delimitado por llaves) que comienza con las declaraciones de variables locales
a la funcin (si existen) y, a continuacin, se tiene el cuerpo de la funcin:
Tipo nombreFun (lista de argumentos)
{
declaraciones
sentencias
}

El Tipo es opcional; en caso de que se omita, se considera que la funcin


devuelve un entero. La lista de argumentos (que puede estar vaca y, en este
caso, se ponen los parntesis con la palabra void en su interior) consta del tipo
y el nombre de cada parmetro formal. Si hay ms de un argumento, stos se
separan por comas. Los argumentos de tipos bsicos se pasan siempre por
valor y los de tipos compuestos siempre por referencia.

Las funciones pueden recibir como parmetros cualquiera de los tipos bsicos
del lenguaje (entero), as como el tipo compuesto que le haya correspondido a
cada grupo.
Las funciones pueden devolver cualquiera de los tipos bsicos del lenguaje
(entero o vaco). Una funcin del tipo void indica que dicha funcin no retorna
ningn valor.
C admite recursividad. Cualquier funcin puede ser recursiva, es decir,
puede llamarse a s misma.
El lenguaje C no permite la definicin de funciones anidadas. Esto implica que
dentro de una funcin no se puede definir otra funcin.
Dentro de una funcin se tiene acceso a las variables locales que se declaren
en dicha funcin, a sus argumentos y a las variables globales. Si en una
funcin se declara una variable local o un argumento con el mismo nombre que
una variable global, sta ltima no es accesible desde dicha funcin.
factorial (int x)
/* se define la funcin recursiva entera con un parmetro entero */
{
if (x > 1)
return x * factorial (x - 1);
else
return 1;
}
void Suma (int aux [], int fin)
/* se define el procedimiento Suma que recibe un vector
por referencia y un entero por valor */
{
for (i= 1; i < fin; i= i + 2)
aux [i]= factorial (aux [i - 1]);
}

Ejemplo de programa para C


/* Programa de ejemplo para el proyecto de Compiladores */
char *s; /* variable global sin inicializar */
int FactorialRecursivo (int n)
/* parmetro entero local a la funcin */
{
if (n == 0)
return 1;
return n * FactorialRecursivo (n - 1);
/* llamada recursiva */
}
int FactorialDo (int n)
{
int factorial = 1; /* variable local inicializada a uno */
do
{
factorial *= n--; /* equivale a: factorial = factorial * n; n = n - 1; */
} while (n);
/* mientras n no sea 0 */

return factorial;

/* devuelve el valor de la variable factorial */

}
int FactorialWhile (int n)
{
int factorial = 1, i = 0;
while (i < n)
factorial *= ++i;
return factorial;
}

/* variables locales inicializadas */


/* equivale a: i = i + 1; factorial = factorial * i; */

int FactorialFor (int n)


{
int i, factorial = 1; /* variables locales */
for (i = 1; i <= n; i++)
factorial *= i;
return factorial;
}
void imprime (char *msg, int f)
/* funcin que recibe una cadena y un entero, pero no devuelve nada
*/
{
puts (s);
puts (msg);
putw (f);
putl (); /* imprime un salto de lnea */
return; /* finaliza la ejecucin de la funcin (en este caso, se podra omitir) */
}
void cuadrados (int z[], int dim)
/* no es necesario indicar el tamao del vector en el parmetro */
/* el vector se pasa por referencia, por tanto los cambios aqu realizados se reflejan fuera */
{
int i;
for (i=0; i < dim; i++)
z[i] *= z[i];
/* z[i] = z[i] * z[i]; */
}
int i;

/*variable global*/

void demo (void) /* funcin sin argumentos que no devuelve nada */


{
int i;
int v[10];
char* z;
z="El primer valor era cero\n";
puts ("Escribe tres nmeros: ");
v[1] = getw ();
v[2] = getw ();
v[3] = getw ();
if (!((v[1] == v[2]) && (v[1] != v[3]))) /* NOT ((v[1] igual a v[2]) AND (v[1] distinto de v[3])) */
v[0] = (v[2] < v[3]) ? v[2]: v[3];
/* si v[2]<v[3], v[0]=v[2]; en otro caso v[0]=v[3] */
if (!v[1])
puts (z);
cuadrados (v, 5);
for (i=0; i < 5; i++)
putw (v[i]);
/* Imprime los elementos del vector al cuadrado */
for (i=1; i <= 10; ++i)
v[i-1]=i;
cuadrados (v, 10);
for (i=0; i <= 9; i++)
putw (v[i]);
/* Imprime los elementos del vector al cuadrado */
}

void main (void) /* funcin principal */


{
int num;
/* variable local a la funcin main */
struct factoriales /* se declara el tipo struct factoriales */
{
int For, Do, While;
/* tiene tres campos enteros */
};
struct factoriales fact;
/* se declara una variable de tipo struct factoriales */
s = "El factorial ";
puts (s);
puts ("Introduce un nmero");
i = getw ();
/* se lee un nmero del teclado */
num= i;
switch (num)
{
case 1:
case 0: puts ("El factorial es 1.\n");
break;
default:
if (num < 0)
puts ("No existe el factorial de un negativo.\n");
else
{
/* se rellenan los campos de la estructura: */
fact.For = FactorialFor (num);
fact.While = FactorialWhile (num);
fact.Do = FactorialDo (num);
imprime ("recursivo es: ", FactorialRecursivo (num));
imprime ("con do-while es: ", fact.Do);
imprime ("con while es: ", fact.While);
imprime ("con for es: ", fact.For);
}
}
demo(); /* llamada a una funcin sin argumentos */
}

También podría gustarte