You are on page 1of 42

MANUAL DE MANEJO DE MIKROC

ZURY JEHEILI SANTIAGO MANZANO.

01/12/2011

INDICE

CARACTERSTICAS PRINCIPALES DEL MIKROC---------------------------------------3

TIPOS DE DATOS EN MIKROC----------------------------------------------------------------8

VARIABLES Y CONSTANTES-----------------------------------------------------------------10

OPERADORES-------------------------------------------------------------------------------------17

ESTRUCTURAS DE CONTROL---------------------------------------------------------------24

TIPOS DE DATOS AVANZADOS--------------------------------------------------------------30

FUNCIONES-----------------------------------------------------------------------------------------36

CARACTERSTICAS PRINCIPALES DEL MIKROC

A continuacin vamos a presentar a los elementos principales del lenguaje mikroC desarrollado por Mikroelektronika. Este lenguaje es muy similar al C estndar, no obstante en determinados aspectos difiere del ANSI estndar en algunas caractersticas. Algunas de estas diferencias se refieren a las mejoras, destinadas a facilitar la programacin de los microcontroladores PIC, mientras que las dems son la consecuencia de la limitacin de la arquitectura del hardware de los PIC. Aqu vamos a presentar caractersticas especficas del lenguaje mikroC en la programacin de los microcontroladores PIC. El trmino C se utilizar para referirse a las caractersticas comunes de los lenguajes C y mikroC.


Este libro describe una aplicacin muy concreta del lenguaje de programacin C utilizado en el compilador mikroC PRO for PIC. En este caso, el compilador se utiliza para la programacin de los microcontroladores PIC.

FASES DE COMPILACIN
El proceso de compilacin consiste en varios pasos y se ejecuta automticamente por el compilador. Por con, un conocimiento bsico del funcionamiento puede ser til para entender el concepto del lenguaje mikroC.

El archivo fuente contiene el cdigo en mikroC que usted escribe para programar el microcontrolador. El preprocesador se utiliza automticamente por el compilador al iniciarse el proceso de la compilacin. El compilador busca las directivas del preprocesador (que siempre empiezan por #) dentro del cdigo y modifica el cdigo fuente de acuerdo con las directivas. En esta fase se llevan a cabo inclusin de archivos, definicin de constantes y macros etc., lo que facilita el proceso. Ms tarde vamos a describir estas directivas en detalle. El analizador sintctico (parser) elimina toda la informacin intil del cdigo (comentarios, espacios en blanco). Luego, el compilador traduce el cdigo a un archivo binario denominado archivo .mcl. El enlazador (linker) recupera toda la informacin requerida para ejecutar el programa de los archivos externos y la agrupa en un solo archivo (.dbg). Adems, un proyecto puede contener ms de un archivo fuente y el programador puede utilizar funciones predefinidas y agrupadas dentro de los archivos denominados libreras. Por ltimo, el generador .hex produce un archivo .hex. Es el archivo que se va a cargar en el microcontrolador.


El proceso entero de la compilacin que incluye todos los pasos anteriormente descritos se le denomina building.

ESTRUCTURA DE PROGRAMA
La idea principal de escribir un programa en C es de romper un problema mayor en varios trozos ms pequeos. Supongamos que es necesario escribir un programa para el microcontrolador para medir la temperatura y visualizar los resultados en un LCD. El proceso de medicin se realiza por un sensor que convierte temperatura en voltaje. El microcontrolador utiliza el convertidor A/D para convertir este voltaje (valor analgico) en un nmero (valor digital) que luego se enva al LCD por medio de varios conductores. En consecuencia, el programa se divide en cuatro partes, de las que cada una corresponde a una accin especfica:

1. 2. 3. 4.

Activar y configurar el convertidor A/D incorporado; Medir el valor analgico; Calcular temperatura; y Enviar los datos en el formato apropiado al LCD;

Los lenguajes de programacin de alto nivel como es C le permiten solucionar este problema con facilidad al escribir cuatro funciones que se ejecutarn cclicamente sin parar. La idea general es de dividir el problema en varios trozos, de los que cada uno se puede escribir como una sola funcin. Todos los programas escritos en mikroC contienen por lo menos una funcin llamada main() que encierra entre llaves {} las sentencias a ser ejecutadas. Esto es la primera funcin a ser ejecutada al iniciarse la ejecucin de programa. Las otras funciones se pueden llamar dentro de la funcin main. En otras palabras, podemos decir que la funcin main() es obligatoria, mientras que las dems son opcionales. Si todava no ha escrito un programa en C, es probable que todo le resulte confuso. No se preocupe, acptelo tal como es por el momento y ms tarde entender la sintaxis.


5

Y ahora, su primer programa real! La figura muestra la estructura de programa, sealando las partes en las que consiste.


La manera de escribir el cdigo en C es muy importante. Por ejemplo, C difiere entre minsculas y maysculas, as que la funcin main() no se puede escribir MAIN() o Main(). Adems, note que dos lneas del cdigo dentro de la funcin terminan con un punto y coma. En C todas las sentencias deben terminar con un punto y coma ;, as el compilador puede aislarlas y traducirlas a cdigo mquina.

COMENTARIOS
Los comentarios son las partes del programa utilizados para aclarar las instrucciones de programa o para proporcionar ms informacin al respecto. El compilador no hace caso a los comentarios y no los compila al cdigo ejecutable. Dicho de manera sencilla, el compilador es capaz de reconocer los caracteres especiales utilizados para designar dnde los comentarios comienzan y terminan y no hace nada de caso al texto entre ellos durante la compilacin. Hay dos tipos de tales caracteres. Unos designan los comentarios largos que ocupan varias lneas de programa marcados por la secuencia especial /*...*/, mientras que otros designan los comentarios cortos que caben en una sola lnea //. Aunque los comentarios no pueden afectar a la ejecucin de programa, son tan importantes como cualquier otra parte de programa. Aqu est el porqu... Con frecuencia es necesario mejorar, modificar, actualizar, simplificar un programa... No es posible interpretar incluso los programas simples sin utilizar los comentarios.

TIPOS DE DATOS EN MIKROC


En el lenguaje C, los datos tienen un tipo, o sea, cada dato utilizado en el programa debe tener su tipo especificado. Esto permite al compilador conocer el tamao de dato (nmero de bytes requerido en la memoria) y su representacin. Hay varios tipos de datos que se pueden utilizar en el lenguaje de programacin mikroC dependiendo del tamao de dato y del rango de valores. La tabla muestra el rango de valores que los datos pueden tener cuando se utilizan en su forma bsica. TAM AO ( NM ERO BI TS) 8 16 32 32

TI PO DE DATO char int float double

DESCRI PCI N

DE

RANGO DE VALORES

Texto (caracteres) Valores enteros Valores en punto flotante Valores en punto flotante de doble precisin

de 0 a 255 de -32768 a 32767 de 1.1754943508210-38 a 6.805647744071038 de 1.1754943508210-38 a 6.805647744071038

*Debido a las limitaciones impuestas por el hardware del microcontrolador, es imposible alcanzar una mayor precisin de datos que la del tipo float. Por eso, el tipo double en mikroC equivale al tipo float.

Al aadir un prefijo (calificador) a cualquier tipo de dato entero o carcter, el rango de sus posibles valores cambia as como el nmero de los bytes de memoria necesarios. Por defecto, los datos de tipo int son con signo, mientras que los de tipo char son sin signo. El calificador signed (con signo) indica que el dato puede ser positivo o negativo. El prefijo unsigned indica que el dato puede ser slo positivo. Note que el prefijo es opcional. TI PO DE DATO CON PREFIJO signed char unsigned int short int int signed short int long int signed long int

TI PO DE DATO char

TAM AO ( NM ERO BI TS) 8 16 8 8 32 32

DE

RANGO DE VALORES

de -128 a 128 de 0 a 65535 de 0 a 255 de -128 a 127 de 0 a 4294967295 de -2147483648 a 2147483647

Tipo entero (int)


Un entero es un nmero sin parte fraccionaria que puede estar expresado en los siguientes formatos:

y y

y y

Hexadecimal (base 16): el nmero empieza con 0x (o 0X). Los enteros hexadecimales consisten en los dgitos (de 0 a 9) y/o las letras (A, B, C,D, E, F). Por ejemplo: 0x1A. Decimal (base 10): el nmero consiste en los dgitos (de 0 a 9). El primer dgito no puede ser 0. En este formato, se puede introducir el signo de nmero (+ o -). Por ejemplo: 569, 25, +1500. Octal (base 8): los nmeros se representan a base 8 utilizando slo 8 dgitos (de 0 a 7). Los enteros octales empiezan con 0. Por ejemplo: 056. Binario: cuando un entero empieza con 0b (o 0B) se representan como una serie de bits (0 y 1). Por ejemplo: 0B10011111

0x11 11 -152 011 0b11

// // // // //

formato formato formato formato formato

hexadecimal equivale a decimal 17 decimal decimal octal equivale a decimal 9 binario equivale a decimal 3

Tipo punto flotante (float)


El tipo punto flotante (float) se utiliza para los nmeros reales con el punto decimal. Los datos de tipo float se pueden representar de varias maneras. Un dato float es siempre consigno (signed).

0. -1.23 23.45e6 2e-5 3E+10 .09E34

// // // // // //

= = = = = =

0.0 -1.23 23.45 * 10^6 2.0 * 10^-5 3.0 * 10^10 0.09 * 10^34

Tipo carcter (char)


El tipo char es considerado como un entero por el compilador. No obstante, se utiliza normalmente para los datos de tipo carcter. Un dato de tipo carcter est encerrado entre comillas y codificado en un carcter ASCII.

59 // entero 'p' // carcter ASCII 'p'


Una secuencia de caracteres es denominada cadena (string). Las cadenas estn encerradas entre comillas dobles, por ejemplo:

"Presione el botn RA0"

VARIABLES Y CONSTANTES

Definiciones
Una variable es un objeto nombrado capaz de contener un dato que puede ser modificado durante la ejecucin de programa. En C, las variables tienen tipo, que significa que es necesario especificar el tipo de dato que se le asigna a una variable (int, float etc.). Las variables se almacenan en la memoria RAM y el espacio de memoria que ocupan (en bytes) depende de su tipo.

/* dos lneas de programa consecutivas. En la primera lnea del programa se define el tipo de variable */ int a = 1000; // Variable a es de tipo int y equivale a 1000 a = 15; // a equivale a 15
Una constante tiene las mismas caractersticas que una variable excepto el hecho de que su valor asignado no puede ser cambiado durante la ejecucin de programa. A diferencia de las variables, las constantes se almacenan en la memoria Flash del microcontrolador para guardar el mayor espacio posible de memoria RAM. El compilador las reconoce por el nombre y el prefijo const. En mikroC, el compilador reconoce automticamente el tipo de dato de una constante, as que no es necesario especificar el tipo adicionalmente.

/* dos lneas de programa consecutivas */ const A = 1000 // el valor de la constante A est definido A = 15; // ERROR! no se puede modificar el valor de la constante
Cada variable o constante debe tener un identificador que lo distingue de otras variables y constantes. Refirase a los ejemplos anteriores, a y A son identificadores.

Reglas para nombrar


En mikroC, los identificadores pueden ser tan largos como quiera. Sin embargo, hay varias restricciones:

y y

Los identificadores pueden incluir cualquiera de los caracteres alfabticos A-Z (a-z), los dgitos 0-9 y el carcter subrayado '_'. El compilador es sensible a la diferencia entre minsculas y maysculas. Los nombres de funciones y variables se escriben con frecuencia con minsculas, mientras que los nombres de constantes se escriben con maysculas. Los identificadores no pueden empezar con un dgito. Los identificadores no pueden coincidir con las palabras clave del lenguaje mikroC, porque son las palabras reservadas del compilador.

10

El compilador mikroC reconoce 33 palabras clave: M IKRO C - PALABRAS CLAVE

absolute asm at auto bit bool break case catch char class code const continue

data default delete do double else enum explicit extern false float for friend goto

if inline int io long mutable namespace operator org pascal private protected public register

return rx sfr short signed sizeof static struct switch template this throw true try

typedef typeid typename union unsigned using virtual void volatile while

11

Ejemplos de los identificadores vlidos e invlidos:

temperatura_V1 Presin no_corresponder dat2string SuM3 _vtexto 7temp %ms_alto especiales if reservada j23.07.04 especiales (punto) nombre de variable Declaracin de variables

// // // // // // //

OK OK OK OK OK OK NO -- no puede empezar con un nmero // NO -- no pueden contener caracteres // NO -- no puede coincidir con una palabra // NO -- no puede contener caracteres

// NO -- no puede contener espacio en blanco

Cada variable debe ser declarada antes de ser utilizada en el programa. Como las variables se almacenan en la memoria RAM, es necesario reservar el espacio para ellas (uno, dos o ms bytes). Al escribir un programa, usted sabe qu tipo de datos quiere utilizar y qu tipo de datos espera como resultado de una operacin, mientras que el compilador no lo sabe. No se olvide de que el programa maneja las variables con los nombres asignados. El compilador las reconoce como nmeros en la memoria RAM sin conocer su tamao y formato. Para mejorar la legibilidad de cdigo, las variables se declaran con frecuencia al principio de las funciones:

<tipo> variable;

Es posible declarar ms de una variable de una vez si tienen el mismo tipo.

<tipo> variable1, variable2, variable3;

Aparte del nombre y del tipo, a las variables se les asignan con frecuencia los valores iniciales justamente enseguida de su declaracin. Esto no es un paso obligatorio, sino una cuestin de buenas costumbres. Se parece a lo siguiente:

unsigned int peso; // Declarar una variable llamada peso peso = 20; // Asignar el valor 20 a la variable peso
Un mtodo ms rpido se le denomina declaracin con inicializacin (asignacin de los valores iniciales):

12

unsigned int peso = 20; // peso est declarado y su valor es 20


Si hay varias variables con el mismo valor inicial asignado, el proceso se puede simplificar:

unsigned int peso1 = peso2 = peso3 = 20; int valor_inicial = un_mnimo_de_petrleo = 0;


y y y Tenga cuidado de no declarar la misma variable otra vez dentro de la misma funcin. Puede modificar el contenido de una variable al asignarle un nuevo valor tantas veces que quiera Al declarar una variable, siempre piense en los valores que la variable tendr que contener durante la ejecucin de programa. En el ejemplo anterior, peso1 no se puede representar con un nmero con punto decimal o un nmero con valor negativo.

Declaracin de constantes
Similar a las variables, las constantes deben ser declaradas antes de ser utilizadas en el programa. En mikroC, no es obligatorio especificar el tipo de constante al declararla. Por otra parte, las constantes deben ser inicializadas a la vez que se declaran. El compilador reconoce las constantes por su prefijo const utilizado en la declaracin. Dos siguientes declaraciones son equivalentes:

const int MINIMUM = -100; // Declarar constante MINIMUM const MINIMUM = -100; // Declarar constante MINIMUM
Las constantes pueden ser de cualquier tipo, incluyendo cadenas:

const T_MAX = 3.260E1; // constante de punto flotante T_MAX const I_CLASS = 'A'; // constante carcter I_CLASS const Mensaje = "Presione el botn IZQUIERDA"; // constante de cadena Mensaje
Las constantes de enumeracin son un tipo especial de constantes enteras que hace un programa ms comprensible al asignar los nmeros ordinales a las constantes. Por defecto, el valor 0 se asigna automticamente a la primera constante entre llaves, el valor 1 a la segunda, el valor 2 a la tercera etc.

enum surtidores {AGUA,GASLEO,CLORO}; // AGUA = 0; GASLEO = 1; CLORO = 2


Es posible introducir directamente el valor de una constante dentro de la lista de enumeraciones. El incremento se detiene al asignar un valor a un elemento de matriz, despus se reinicia a partir del valor asignado. Vea el siguiente ejemplo:

13

enum surtidores {AGUA,GASLEO=0,CLORO}; // AGUA = 0; GSOLEO = 0; CLORO = 1


Las constantes de enumeracin se utilizan de la siguiente manera:

int Velocidad_de_ascensor enum motor_de_ascensor {PARADA,INICIO,NORMAL,MXIMO}; Velocidad_de_ascensor = NORMAL; // Velocidad_de_ascensor = 2 Definir los nuevos tipos de datos
La palabra clave typedef le permite crear con facilidad los nuevos tipos de datos.

typedef unsigned int positivo; // positivo es un sinnimo para el tipo sin signo int positivo a,b; // Variables a y b son de tipo positivo a = 10; // Variable a equivale a 10 b = 5; // Variable b equivale a 5 mbito de variables y constantes
Una variable o una constante es reconocida por el compilador en base de su identificador. Un identificador tiene significado si el compilador lo puede reconocer. El mbito de una variable o una constante es el rango de programa en el que su identificador tiene significado. El mbito es determinado por el lugar en el que se declara una variable o una constante. Intentar acceder a una variable o una constante fuera de su mbito resulta en un error. Una variable o una constante es invisible fuera de su mbito. Todas las variables y constantes que pensamos utilizar en un programa deben ser declaradas anteriormente en el cdigo. Las variables y constantes pueden ser globales o locales. Una variable global se declara en el cdigo fuente, fuera de todas las funciones, mientras que una variable local se declara dentro del cuerpo de la funcin o dentro de un bloque anidado en una funcin.

14


A las variables globales se les puede acceder de cualquiera parte en el cdigo, an dentro de las funciones con tal de que sean declaradas. El mbito de una variable global est limitado por el fin del archivo fuente en el que ha sido declarado.

El mbito de variables locales est limitado por el bloque encerrado entre llaves {} en el que han sido declaradas. Por ejemplo, si estn declaradas en el principio del cuerpo de funcin (igual que en la funcin main) su mbito est entre el punto de declaracin y el fin de esa funcin. Refirase al ejemplo anterior. A las variables locales declaradas en main() no se les puede acceder desde la Funcin_1 y al revs. Un bloque compuesto es un grupo de declaraciones y sentencias (que pueden ser bloques tambin) encerradas entre llaves. Un bloque puede ser una funcin, una estructura de control etc. Una variable declarada dentro de un bloque se considera local, o sea, existe slo dentro del bloque. Sin embargo, las variables declaradas fuera del mbito todava son visibles. Aunque las constantes no pueden ser modificadas en el programa, siguen las mismas reglas que las variables. Esto significa que son visibles dentro de su bloque a excepcin de las constantes globales (declaradas fuera de cualquier funcin). Las constantes se declaran normalmente en el inicio del cdigo fuera de cualquier funcin (como variables globales).

15

Clases de almacenamiento
Las clases de almacenamiento se utilizan para definir el mbito y la vida de variables, constantes y funciones dentro de un programa. En mikroC se pueden utilizar diferentes clases de almacenamiento:

auto es una clase de almacenamiento por defecto para las variables locales, as que se utiliza raramente. Se utiliza para definir que una variable local tiene duracin local. La clase de almacenamiento auto no se puede utilizar con variables globales.

static es una clase de almacenamiento por defecto para las variables globales. Especifica que una variable es visible dentro del archivo. A las variables locales declaradas con el prefijo static se les puede acceder dentro del archivo fuente (o sea se comportan como variables globales). extern: la palabra clave extern se utiliza cuando el programa est compuesto por diferentes archivos fuente. Esto le permite utilizar una variable, una constante o una funcin declarada en otro archivo. Por supuesto, para compilar y enlazar este archivo correctamente, el mismo debe ser incluido en su proyecto. En los siguientes ejemplos, el programa consiste en dos archivos: File_1 y File_2. El File_1 utiliza una variable y una funcin declaradas en File_2.

File 1:

extern int cnt; // Variable cnt es visible en File_1 extern void hello(); // Funcin hello()se puede utilizar File_1

en

void main(){ PORTA = cnt++; // Cualquier modificacin de cnt en File_1 ser visible en File_2 hello(); // Funcin hello()se puede llamar desde aqu }
File 2:

int cnt = 0; void hello(); void hello(){ // Modificaciones que afectan a la . // cnt en File_1 son visibles aqu . . }

16

OPERADORES

Un operador es un smbolo que denota una operacin aritmtica, lgica u otra operacin particular. Dicho de manera sencilla, varias operaciones aritmticas y lgicas se realizan por medio de los operadores. Hay ms de 40 operaciones disponibles en el lenguaje C, pero se utiliza un mximo de 10-15 de ellas en prctica. Cada operacin se realiza sobre uno o ms operandos que pueden ser variables o constantes. Adems, cada operacin se caracteriza por la prioridad de ejecucin y por la asociatividad.

OPERADORES ARITMTICOS
Los operadores aritmticos se utilizan en las operaciones aritmticas y siempre devuelven resultados numricos. Hay dos tipos de operadores, los unitarios y los binarios. A diferencia de las operaciones unitarias que se realizan sobre un operando, las operaciones binarias se realizan sobre dos operandos. En otras palabras, se requieren dos nmeros para ejecutar una operacin binaria. Por ejemplo: a+b o a/b. O PERADO R O PERACI N

+ * / %

Adicin Resta Multiplicacin Divisin Resto de la divisin

int a = b = c = c =

a,b,c; 5; 4; a + b; c%2;

// // // // // // // //

Declarar 3 enteros a, b, c Inicializar a Inicializar b c = 9 c = 1. Esta operacin se utiliza con frecuencia para comprobar la paridad. En este caso, el resultado es 1 lo que significa que la variable es un nmero imparo

OPERADORES DE ASIGNACIN
Hay dos tipos de asignacin en el lenguaje C:

17

y y

Los operadores simples asignan los valores a las variables utilizando el carcter comn '='. Por ejemplo: a =8 Las asignaciones compuestas son especficas para el lenguaje C. Consisten en dos caracteres como se muestra en la tabla a la derecha. Se utilizan para simplificar la sintaxis y habilitar la ejecucin ms rpida.
EJEMPLO

O PERADO R Expresin a += 8 a -= 8 a *= 8 a /= 8 a %= 8 Equivalente a=a+8 a=a-8 a=a*8 a=a/8 a=a%8

+= -= *= /= %=

int a = 5; // Declarar e inicializar la variable a a += 10; // a = a + 10 = 15

OPERADORES DE INCREMENTO Y DECREMENTO


Las operaciones de incremento y decremento por 1 se denotan con "++" y "--". Estos caracteres pueden preceder o seguir a una variable. En primer caso (++x), la variable x ser incrementada por 1 antes de ser utilizada en la expresin. De lo contrario, la variable se utilizar en la expresin antes de ser aumentada por 1. Lo mismo se aplica a la operacin de decremento O PERADO R EJEMPLO DESCRI PCI N

++

++a

Variable

"a"

es

18

a++

incrementada por 1

--b -b--

Variable "a" es decrementada por 1

int a = c = b =

a, b, c; b = 5; 1 + a++; // c = 6 ++c + a // b = 7 + 6 = 13

OPERADORES RELACIONALES
Los operadores relacionales se utilizan en comparaciones con el propsito de comparar dos valores. En mikroC, si una expresin es evaluada como falsa (false), el operador devuelve 0, mientras que si una oracin es evaluada como verdadera (true), devuelve 1. Esto se utiliza en expresiones tales como si la expresin es evaluada como verdadera, entonces... O PERADO R DESCRI PCI N EJEMPLO CO NDI CI N DE VERACI DAD

>

mayor que mayor o igual que menor que menor o igual que igual que desigual que

b>a a >= 5 a<b a <= b a == 6 a != b

si b es mayor que a si a es mayor o igual que 5 si a es menor que b si a es menor o igual que b si a es igual que 6 si a es desigual que b

>= < <=

== !=

int prop; int var = 5; prop = var < 10; // Expresin es evaluada como verdadera, prop = 1

19

OPERADORES LGICOS
Hay tres tipos de operaciones lgicas en el lenguaje C: Y (AND) lgico, O (OR) lgico y negacin - NO (NOT) lgico. Los operadores lgicos devuelven verdadero (1 lgico) si la expresin evaluada es distinta de cero. En caso contrario, devuelve falso (0 lgico) si la expresin evaluada equivale a cero. Esto es muy importante porque las operaciones lgicas se realizan generalmente sobre las expresiones, y no sobre las variables (nmeros) particulares en el programa. Por lo tanto, las operaciones lgicas se refieren a la veracidad de toda la expresin. Por ejemplo: 1 && 0 es igual a (expresin verdadera) && (expresin falsa) El resultado 0, o sea - Falso en ambos casos. O PERADO R FUNCIN

&& || !

Y O NO

OPERADORES DE MANEJO DE BITS


A diferencia de las operaciones lgicas que se realizan sobre los valores o expresiones, las operaciones de manejo de bits se realizan sobre los bits de un operando. Se enumeran en la siguiente tabla: O PERADO R DESCRI PCI N EJEMPLO RESULTADO

Complemento a uno

a = ~b

b=5

a = -5 a = 11001100 a = 00011110

<<

Desplazamiento a la izquierda

a = b << 2

b = 11110011

>>

Desplazamiento a la derecha

a = b >> 2

b = 11110011

&

Y lgico para manejo de bits

c=a&b

a = 11100011 b = 11001100 a 11100011

c = 11000000

O lgico para manejo de bits

c=a|b

20

b = 11001100 a = 11100011 b = 11001100

11101111

EXOR lgico para manejo de bits

c=a^b

c = 00101111

Note que el resultado de la operacin de desplazamiento a la derecha depende del signo de la variable. En caso de que el operando se aplique a una variable sin signo o positiva, se introducirn los ceros en el espacio vaco creado por desplazamiento. Si se aplica a un entero con signo negativo, se introducir un 1 para mantener el signo correcto de la variable.

CMO UTILIZAR LOS OPERADORES?

Aparte de los operadores de asignacin, dos operadores no deben estar escritos uno junto al otro.
x*%12; // esta expresin generar un error

y y

Cada operador tiene su prioridad y asociatividad como se muestra en la tabla: Similar a las expresiones aritmticas, los operadores se agrupan juntos por medio de parntesis. Primero se calculan las expresiones encerradas entre parntesis. Si es necesario, se pueden utilizar los parntesis mltiples (anidados).
O PERADO RES ASO CI ATI VI DAD

PRIO RI DAD

Alta

() [] -> .

de izquierda a derecha

! ~ ++ -- +(unitario) -(unitario) *Puntero &Puntero

de derecha a izquierda

* / % + Baja < > < <= > >= == != &

de izquierda a derecha de izquierda a derecha de izquierda a derecha de izquierda a derecha de izquierda a derecha de izquierda a derecha

21

^ | && || ?:

de izquierda a derecha de izquierda a derecha de izquierda a derecha de derecha a izquierda de derecha a izquierda

= += -= *= /= /= &= ^= |= <= >=

de izquierda a derecha

int a = b = res res

a, b, res; 10; 100; = a*(a + b); // resultado = 1100 = a*a + b; // resultado = 200

CONVERSIN DE TIPOS DE DATOS


Algunas operaciones implican conversin de datos. Por ejemplo, si divide dos valores enteros, hay una alta posibilidad de que el resultado no sea un entero. El mikroC realiza una conversin automtica cuando se requiera.

Si dos operandos de tipo diferente se utilizan en una operacin aritmtica, el tipo de operando de la prioridad ms baja se convierte automticamente en el tipo de operando de la prioridad ms alta. Los tipos de datos principales se colocan segn el siguiente orden jerrquico:


La autoconversin se realiza asimismo en las operaciones de asignacin. El resultado de la expresin de la derecha del operador de la asignacin siempre se convierte en el tipo de la variable de la izquierda del operador. Si el resultado es de tipo de la prioridad ms alta, se descarta o se redondea para coincidir con el tipo de la variable. Al convertir un dato real en un entero, siempre se descartan los nmeros que siguen al punto decimal.

22

int x; // A la variable x se le asigna el tipo integer (un entero) x = 3; // A la variable x se le asigna el valor 3 x+ = 3.14; // El valor 3.14 se agrega a la variable x al // realizar la operacin de asignacin /* El resultado de la adicin es 6 en vez de 6.14, como era de esperar. Para obtener el resultado esperado sin descartar los nmeros que siguen al punto decimal, se debe declarar x como un punto flotante. */
Para realizar una conversin explcita, antes de escribir una expresin o una variable hay que especificar el tipo de resultado de operacin entre parntesis.

double distancia, tiempo, velocidad; distancia = 0.89; tiempo = 0.1; velocidad = (int)(a/b); // c = (int)8.9 = 8.0 velocidad = ((int)a)/b; // c = 0/0.1 = 0.0

23

ESTRUCTURAS DE CONTROL
ESTRUCTURAS CONDICIONALES
Las condiciones son ingredientes comunes de un programa. Las condiciones permiten ejecutar una o varias sentencias dependiendo de validez de una expresin. En otras palabras, Si se cumple la condicin (...), se debe hacer (...). De lo contrario, si la condicin no se cumple, se debe hacer (...). Los operandos condicionales if-else y switch se utilizan en las operaciones condicionales. Una sentencia condicional puede ser seguida por una sola sentencia o por un bloque de sentencias a ser ejecutadas.

OPERADOR CONDICIONAL if-else


El operador if se puede utilizar solo o asociado al operador else (if-else). Ejemplo del operador if:

if(expresin) operacin;
Si el resultado de la expresin encerrada entre parntesis es verdadero (distinto de 0) la operacin se realiza y el programa contina con la ejecucin. Si el resultado de la expresin es falso (0), la operacin no se realiza y el programa contina inmediatamente con la ejecucin. Como hemos mencionado, la otra forma combina tanto el operador if como el else:

if(expresin) operacin1 else operacin2;


Si el resultado de la expresin es verdadero (distinto de 0), se realiza operacin1, de lo contrario se realiza la operacin2. Despus de realizar una de las operaciones, el programa contina con la ejecucin. La sentencia if-else se parece a lo siguiente:

if(expresin) operacin1 else operacin2


Si operacin1 u operacin2 est compuesta, escriba una lista de sentencias encerradas entre llaves. Por ejemplo:

if(expresin) { ... // ... // operacin1 ...} // else operacin2


El operador if-else se puede sustituir por el operador condicional '?:':

24

(expresin1)? expresin2 : expresin3

Si el valor de la expresin1 es distinto de 0 (verdadero), el resultado de la expresin entera ser equivalente al resultado obtenido de laexpresin2. De lo contrario, si la expresin1 es 0 (falso), el resultado de la expresin entera ser equivalente al resultado obtenido de laexpresin3. Por ejemplo:

maximum = (a>b)? a : b // A la variable maximum se le asigna el // valor de la variable mayor(a o b)


Operador Switch
A diferencia de la sentencia if-else que selecciona entre dos opciones en el programa, el

operador switch permite elegir entre varias opciones. La sintaxis de la sentencia switch es:

switch (selector) // Selector es de tipo char o int { case constante1: operacin1 // El grupo de operadores que se ejecutan si ... // el selector y la constante1 son equivalentes break; case constante2: operacin2 // El grupo de operadores se ejecuta si ... // el selector y la constante2 equivalentes break; ... default: operacin_esperada ejecuta si ... selector break; } // El grupo de operadores que se son

// ninguna constante equivale al

La operacin switch se ejecuta de la siguiente manera: primero se ejecuta el selector y se compara con la constante1. Si coinciden, las sentencias que pertenecen a ese bloque se ejecutan hasta llegar a la palabra clave break o hasta el final de la operacin switch. Si no coinciden, el selector se compara con la constante2. Si coinciden, las sentencias que pertenecen a ese bloque se ejecutan hasta llegar a la palabra clave break etc. Si el selector no coincide con ninguna constante, se ejecutarn las operaciones que siguen al operador default.

25

Tambin es posible comparar una expresin con un grupo de constantes. Si coincide con alguna de ellas, se ejecutarn las operaciones apropiadas:

switch (das) // La variable das representa un da de la semana. { // Es necesario determinar si es un da laborable o no lo es case1:case2:case3:case4:case5: LCD_message = 'Da laborable'; break; case6:case7: LCD_message = 'Fin de semana'; break; default:LCD_message_1 = 'Elija un da de la semana'; break; }
La palabra clave de C break se puede utilizar en cualquier tipo de bloques. Al utilizar break, es posible salir de un bloque aunque la condicin para su final no se haya cumplido. Se puede utilizar para terminar un bucle infinito, o para forzar un bucle a terminar antes de lo normal.

BUCLES
A menudo es necesario repetir una cierta operacin un par de veces en el programa. Un conjunto de comandos que se repiten es denominado un bucle de programa. Cuntas veces se ejecutar, es decir cunto tiempo el programa se quedar en el bucle, depende de las condiciones de salir del bucle.

Bucle While
El bucle while se parece a lo siguiente:

while(expresin){ comandos ... }


Los comandos se ejecutan repetidamente (el programa se queda en el bucle) hasta que la expresin llegue a ser falsa. Si la expresin es falsa en la entrada del bucle, entonces el bucle no se ejecutar y el programa continuar desde el fin del bucle while.

Un tipo especial del bucle de programa es un bucle infinito. Se forma si la condicin sigue sin cambios dentro del bucle. La ejecucin es simple en este caso ya que el resultado entre llaves es siempre verdadero (1=verdadero), lo que significa que el programa se queda en el mismo bucle:

while(1){ // En vez de "while(1)", se puede escribir "while(true)" ... // Expresiones encerradas entre llaves se ejecutarn ... // repetidamente (bucle infinito) } Bucle For 26

El bucle for se parece a lo siguiente:

for(expresin_inicial; expresin_de_condicin; cambiar_expresin) { operaciones ... }


La ejecucin de esta secuencia de programa es similar al bucle while, salvo que en este caso el proceso de especificar el valor inicial (inicializacin) se realice en la declaracin. La expresin_ inicial especifica la variable inicial del bucle, que ms tarde se compara con la expresin_ de_condicin antes de entrar al bucle. Las operaciones dentro del bucle se ejecutan repetidamente y despus de cada iteracin el valor de la expresin_inicial se incrementa de acuerdo con la regla cambiar_expresin. La iteracin contina hasta que la expresin_de_condicin llegue a ser falsa.

for(k=0; k<5; k++) // La variable k se incrementa 5 veces (de 1 a 4) y operacin // cada vez se repite la expresin operacin ...
La operacin se ejecutar cinco veces. Luego, al comprobar se valida que la expresin k<5 sea falsa (despus de 5 iteraciones k=5) y el programa saldr del bucle for.

Bucle Do-while
El bucle do-while se parece a lo siguiente:

do operacin while (cambiar_condicin);


La expresin cambiar_condicin se ejecuta al final del bucle, que significa que operacin se ejecuta como mnimo una vez sin reparar en que si la condicin es verdadera o falsa. Si el resultado es distinto de 0 (verdadero), el procedimiento se repite.

Todos los siguientes ejemplos son equivalentes. Esta parte del cdigo visualiza "hello" en un LCD 10 veces con un retardo de un segundo. Note que en este ejemplo se utilizan funciones predefinidas, que se encuentran en las libreras del compilador mikroC PRO for PIC. No obstante le aconsejamos que no trate de entenderlas en detalle. Su comportamiento general dentro del bucle se explica por medio de los comentarios.

i = 0; // Inicializacin del contador while (i<10) { // Condicin Lcd_Out(1,3,"hello"); // Visualizar hello en el LCD Delay_ms(1000); // Retardo de 1000 ms 27

Lcd_Cmd(_LCD_CLEAR); Delay_ms(500); i++;

// Borrar el LCD // Retardo de 500ms // Contador se incrementa

} for(i=0; i<10; i++) { // Inicializacin, condicin, incremento Lcd_Out(1,3,"hello"); // Visualizar hello en el LCD Delay_ms(1000); // Retardo de 1000 ms Lcd_Cmd(_LCD_CLEAR); // Borrar el LCD Delay_ms(500); // Retardo de 500ms } i = 0; // Inicializacin del contador do { Lcd_Out(1,3,"hello"); // Visualizar hello en el LCD Delay_ms(1000); // Retardo de 1000 ms Lcd_Cmd(_LCD_CLEAR); // Borrar LCD Delay_ms(500); // Retardo de 500ms i++; // Contador se incrementa } while (i<10); // Condicin SENTENCIAS DE SALTO
SENTENCIA BREAK
A veces es necesario detener y salir de un bucle dentro de su cuerpo. La sentencia break se puede utilizar dentro de cualquier bucle (while, for, do while) y en las sentencias switch tambin. En stas la sentencia break se utiliza para salir de las sentencias switch si la condicin case es verdadera. En este ejemplo, Esperar est parpadeando en la pantalla LCD hasta que el programa detecte un uno lgico en el pin 0 del puerto PORTA.

while(1){ // Bucle infinito if(PORTA.F0 == 1) // Probar si el estado lgico del pin 0 del puerto break; // PORTA es 1; si equivale, salir del bucle Lcd_Out(1,3,"Esperar"); // Visualizar Esperar en el LCD Delay_ms(1000); // Retardo de 1000 ms Lcd_Cmd(_LCD_CLEAR); // Borrar LCD Delay_ms(500); // Retardo de 500ms }
SENTENCIA CONTINUE
La sentencia continue colocada dentro de un bucle se utiliza para saltar una iteracin. A diferencia de la sentencia break, el programa se queda dentro del bucle y las iteraciones continan.

// Si x=7, puede ocurrir una divisin por 0. // continue se utiliza aqu para evitar esta situacin. 28

x=1; while (x<=10) { if (x == 7) { // saltar x=7 para evitar divisin por 0 Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,3,"Division by 0"); Delay_ms(1000); x++; continue; // Despus de esta lnea, saltar a la sentencia while con x=8 } a = 1/(x-7); // Esta divisin generar un error si x=7 /* Muchas operaciones pueden ocurrir aqu */ Lcd_Out(1,3,"Division is OK"); // Poner este mensaje en el LCD Delay_ms(1000); x++; }
SENTENCIA GOTO
La sentencia goto le permite hacer un salto absoluto al otro punto en el programa. Esta caracterstica se debe utilizar con precaucin ya que su ejecucin puede causar un salto incondicional sin hacer caso a todos los tipos de limitaciones de anidacin. El punto destino es identificado por una etiqueta, utilizada como un argumento para la sentencia goto. Una etiqueta consiste en un identificador vlido seguido por un colon (:).

... if(CO2_sensor) goto aire acondicionado; // Si se consta que el valor ... // de la variable CO2_sensor =1 // hacer salto a la lnea de programa // Aire acondicionado ... Aire acondicionado: // Desde aqu sigue la parte del cdigo que se ejecutar // en caso de una concentracin de CO2 demasiado alta ... // en el ambiente

29

TIPOS DE DATOS AVANZADOS


MATRICES
Una matriz es una lista de elementos del mismo tipo colocados en localidades de memoria contiguas. Cada elemento es referenciado por un ndice. Para declarar una matriz, es necesario especificar el tipo de sus elementos (denominado tipo de matriz), su nombre y el nmero de sus elementos encerrados entre corchetes. Todos los elementos de una matriz tienen el mismo tipo.

tipo_de_matriz nombre_de_matriz [n_de_elementos];


Los elementos de una matriz se identifican por su posicin. En C, el ndice va desde 0 (el primer elemento de una matriz) a N-1 (N es el nmero de elementos contenidos en una matriz). El compilador tiene que saber cuntas localidades de memoria debe alojar al declarar una matriz. El tamao de una matiz no puede ser una variable. Por eso, se pueden utilizar dos mtodos:

// mtodo 1 int display [3]; // Declaracin de la matriz display capaz de contener 3 enteros // mtodo 2 const DGITOS = 5; char Matriz_nueva[DGITOS]; // Declaracin de la matriz Matriz_nueva // capaz de contener 5 enteros
Una matriz se puede inicializar a la vez que se declara, o ms tarde en el programa. En ambos casos, este paso se realiza al utilizar llaves:

 
int array_1[3] = {10,1,100};

30

Para leer o modificar un elemento de matriz del ejemplo anterior, basta con introducir su ndice encerrado entre corchetes:

/* Se supone que a ha sido declarado anteriormente como un entero */ a = array_1[0]; // A la variable a se le asigna el valor del miembro de matriz // con ndice 0 (a = 10) array_1[2] = 20; // Miembro de matriz array_1[2] es modificado (nuevo valor es 20)
El siguiente programa cambia el orden de los elementos de una matriz. Note que el ndice se puede expresar mediante variables y operaciones bsicas.

void main() { const MUESTRAS_DE_AGUA = 4; // Valor de la constante MUESTRAS_DE_AGUA es 4 int i, temp; // Variables i y temp son de tipo int int profunidad_de_sonda [MUESTRAS_DE_AGUA] = {24,25,1,1987};// Todos // los miembros de la matriz profundidad // de sonda son de tipo int for(i=0;i<(MUESTRAS_DE_AGUA/2);i++){ veces temp = profundiad_de_sonda [i]; guardar un valor // Bucle se ejecuta 2

// temp se utiliza para

// temporalmente profundiad_de_sonda [i] = profundiad_de_sonda [MUESTRAS_DE_AGUA-1-i]; profundiad_de_sonda [MUESTRAS_DE_AGUA-1-i] = temp; } // Aqu tenemos: {1987,1,25,24} } profundidad_de_sonda [MUESTRAS_DE_AGUA] =

MATRICES BIDIMENSIONALES
Aparte de las matrices unidimensionales que se pueden interpretar como una lista de valores, el lenguaje C le permite declarar matrices multidimensionales. En esta parte vamos a describir slo las matrices bidimensionales, tambin denominadas tablas o matrices. Una matriz bidimensional se declara al especificar el tipo de dato de matriz, el nombre de matriz y el tamao de cada dimensin.

31

tipo_de_matriz [nmero_de_columnas];

nombre_de_matriz

[nmero_de_filas]

En la declaracin de esta matriz nmero_de_filas y nmero_de_columnas representan el nmero de filas y columnas en las que consiste una tabla, respectivamente. Vea la siguiente matriz bidimensional:

int Tabla [3][4]; // Tabla se define de modo que tenga 3 filas y 4 columnas
Esta matriz se puede representar en la forma de una tabla. tabla[0][0] tabla[1][0] tabla[2][0] tabla[0][1] tabla[1][1] tabla[2][1] tabla[0][2] tabla[1][2] tabla[2][2] tabla[0][3] tabla[1][3] tabla[2][3]

Similar a las matrices unidimesionales, es posible asignar los valores a los elementos de una tabla en la lnea de declaracin. La asignacin debe ser realizada lnea a lnea como en el siguiente ejemplo. Como hemos visto anteriormente, esta matriz tiene dos filas y tres columnas:

int Tabla [2][3]= { {3,42,1},{7,7,19} };


La matriz anterior se puede representar tambin en la forma de una tabla de valores: 3 7 42 7 1 19

PUNTEROS
Un puntero es una variable destinada a recibir una direccin. Un puntero apunta a una localidad de memoria, referenciada por una direccin. En C, la direccin de un objeto se puede obtener por medio un operador unitario &. Para acceder al contenido de la memoria en una direccin especfica (tambin llamado objeto apuntado), se utiliza un operador de indireccin (*).

32


'&n' es la direccin de la localidad de memoria 'n'. '*(&n)' es el contenido de la direccin '(&n)', o sea de 'n'. Para declarar un puntero, se debe que especificar el tipo de la variable apuntada:

tipo_de_variable *puntero;
En esta etapa, el puntero mi_puntero apunta al valor almacenado en esta localidad de memoria, o sea, a un valor desconocido. As que, una inicializacin es muy recomendable:

puntero = &variable;

Ahora, puntero contiene la direccin de variable. Para acceder al contenido de la variable apuntada, debe utilizar *. El siguiente ejemplo muestra el contenido de memoria dependiendo de la accin realizada por medio del puntero.


Los punteros son muy tiles para manejar las matrices. En este caso, un puntero se utilizar para apuntar al primer elemento de una matriz. Debido al hecho de que es posible realizar operaciones bsicas sobre los punteros (aritmtica de punteros), es fcil manejar los elementos de una matriz. Fjese en la diferencia entre *v+1 y *(v+1) en el siguiente ejemplo:

short int voltio[3] = {0,5,10}; 33

short int *v; v = &(voltio[0]); *(v+1) = 2; voltio[2] = *v+1; *(v+2) = *(v+1); v++; *v = 1;
y y

// // // // // //

v contiene la direccin de voltio[0] voltio[1] = 2 tab[2] = 1 (tab[0] + 1) voltio[2] = 2 v contiene la direccin de voltio[1] voltio[1] = 1

Los punteros tambin pueden ser declarados con el prefijo const. En este caso, su valor no puede ser modificado despus de la inicializacin, similar a una constante. A diferencia de C, el mikroC no admite alojamiento dinmico.

ESTRUCTURAS
Ya hemos visto cmo agrupar los elementos dentro de matrices. No obstante, al utilizar este mtodo todos los elementos deben ser del mismo tipo. Al utilizar estructuras, es posible agrupar diferentes tipos de variables bajo el mismo nombre. Las variables dentro de una estructura se le denominan los miembros de la estructura. Las estructuras de datos se declaran al utilizar la siguiente sintaxis:

struct nombre_de_estructura { tipo1_de_miembro1 miembro1; tipo2_de_miembro2 miembro2; tipo3_de_miembro3 miembro3; .. };


No es posible inicializar variables dentro de la declaracin de la estructura de datos:

struct generador { int voltaje; char corriente; };


Entonces, podr definir los objetos denominados turbina en el cdigo. A cada uno de estos tres objetos (turbinas) se le asignan las variables corriente y voltaje.

struct generadores turbina_1, turbina_2, turbina_3;


Para acceder a las variables, es preciso utilizar el operador '.'

turbina_3.voltaje = 150; turbina_3.corriente = 12;

34

Por supuesto, igual que al utilizar los punteros, todava se le permite realizar operaciones por medio de operadores y sentencias definidos en las partes anteriores.

Si est familiarizado con el lenguaje C, recuerde que mikroC no admite la inicializacin de los miembros de estructura por medio de las llaves. Por ejemplo, conjunto_1 ={15,m}; devuelve un error en mikroC.

FUNCIONES
Una funcin es una subrutina que contiene una lista de sentencias a realizar. La idea principal es dividir un programa en varias partes utilizando estas funciones para resolver el problema inicial con ms facilidad. Adems, las funciones nos permiten utilizar las destrezas y el conocimiento de otros programadores. Una funcin se ejecuta cada vez que se llame dentro de otra funcin. En C, un programa contiene como mnimo una funcin, la funcin main(), aunque el nmero de funciones es normalmente mayor. Al utilizar funciones el cdigo se hace ms corto ya que es posible llamar una funcin tantas veces como se necesite. En C, el

35

cdigo normalmente consiste en muchas funciones. No obstante, en caso de que su programa sea muy corto y simple, puede escribir todas las sentencias dentro de la funcin principal.

FUNCIN PRINCIPAL
La funcin principal main() es una funcin particular puesto que es la que se ejecuta al iniciar el programa. Adems, el programa termina una vez completada la ejecucin de esta funcin. El compilador reconoce automticamente esta funcin y no es posible llamarla por otra funcin. La sintaxis de esta funcin es la siguiente:

void main (void) { /* el primer 'void' significa que main no devuelve ningn valor. El segundo 'void' significa que no recibe ningn valor. Note que el compilador tambin admite la siguiente sintaxis: 'main()' o 'void main()' o 'main(void)' */ .. /* --- Introduzca su programa aqu --- */ . };
Esto significa que f es una funcin que recibe un nmero real x como parmetro y devuelve 2*x-y. La misma funcin en C se parece a lo siguiente:

float f (float x, float y) // variables flotantes x y y se pueden utilizar en f { float r; // declarar r para almacenar el resultado r = 2*x - y; // almacenar el resultado del clculo en r return r; // devolver el valor de r }
Cada funcin debe ser declarada apropiadamente para poder interpretarla correctamente durante el proceso de compilacin. La declaracin contiene los siguientes elementos:

y y y

Tipo de resultado (valor devuelto): tipo de dato del valor devuelto Nombre de funcin: es un identificador que hace posible llamar a una funcin. Declaracin de parmetros se parece a la declaracin de variable regular (por ejemplo: float x). Cada parmetro consiste en una variable, constante, puntero o matriz, precedidos

36

por la etiqueta de tipo de dato. Se utilizan para pasar la informacin a la funcin al llamarla. Los parmetros diferentes estn delimitados por comas. Cuerpo de funcin: bloque de sentencias dentro de llaves

Una funcin se parece a lo siguiente:

tipo_de_resultado argumento2,...) { Sentencia; Sentencia; ... return ... }

nombre_de_funcin

(tipo

argumento1,

tipo

Note que una funcin no necesita parmetros (funcin main() por ejemplo), pero debe estar entre parntesis. En caso contrario, el compilador malinterpretara la funcin. Para hacerlo ms claro, puede sustituir el espacio en blanco encerrado entre parntesis por la palabra clave void: main (void).

VALOR DEVUELTO
Una funcin puede devolver un valor (esto no es obligatorio) por medio de la palabra clave return. Al llegar a return, la funcin evala un valor (puede ser una expresin) y lo devuelve a la lnea de programa desde la que fue llamada.

return r; // Devolver el valor contenido en r return (2*x - y); // Devolver el valor de la expresin 2*x-y
Una funcin no puede devolver ms de un valor, pero puede devolver un puntero o una estructura. Tenga cuidado al utilizar matrices y punteros. El siguiente ejemplo es un error tpico:

int *reverse(int *tab) // Esta funcin debe devolver una matriz r { // cuyo contenido est en orden inverso con // respecto a la matriz tab int r[DIM]; // Declaracin de una nueva matriz denominada r int i; for(i=0;i<DIM;i++) // Bucle que copia el contenido de tab en r r[i] = tab[DIM-1-i]; // al invertir el orden return r; // Devolver el valor r }
En realidad, el compilador reserva memoria para el almacenamiento de variables de la funcin reverse slo durante su ejecucin. Una vez completada la ejecucin de reverse, la localidad de memoria para la variable i o

37

para la matriz r ya no est reservada. Esto significa que la direccin que contiene los valores de i o r[] est libre para introducir datos nuevos. Concretamente, la funcin devuelve slo el valor &r[0], as que slo el primer elemento de la matriz tab ser almacenado en la memoria. Las dems localidades de memoria, tales como &tab[1], &tab[2], etc. sern consideradas por el compilador como espacios en blanco, o sea, estarn listas para recibir los nuevos valores.

Para escribir esta funcin es necesario pasar la matriz r [] como parmetro (vea la subseccin Pasar los parmetros).

La funcin puede contener ms de una sentencia return. En este caso, al ejecutar la primera sentencia return, la funcin devuelve el valor correspondiente y se detiene la ejecucin de la funcin.

float abs (float x, float y) // Devolver el valor absoluto de 2*x-y { if ((2*x - y) >= 0) return (2*x - y); else return (-2*x + y); }
Si la funcin no devuelve ningn valor, la palabra void debe ser utilizada como un tipo de resultado en la declaracin. En este caso, la sentencia return no debe ser seguida por ninguna expresin. Puede ser omitida como en el siguiente ejemplo:

void wait_1 (unsigned int a) { cnt ++; // Incremento de una variable global cnt Delay_ms(a) ; // Ejecucin de la funcin Delay_ms } // Note que Delay_ms no devuelve nada DECLARAR PROTOTIPOS DE FUNCIONES
Para utilizar una funcin, el compilador debe ser consciente de su presencia en el programa. En la programacin en C, los programadores normalmente primero escriben la funcin main() y luego las funciones adicionales. Para avisar al compilador de la presencia de las funciones adicionales, se requiere declarar los prototipos de funciones en el principio de programa antes de la funcinmain(). Un prototipo de funcin est compuesto por:

y y y y

tipo de resultado nombre de funcin tipos de parmetros un punto y coma (;)

38

El prototipo de la funcin main no necesita ser declarado.

float f (float, float); /* no es obligatorio escribir los nombres de los parmetros. Este prototipo informa al compilador: en el programa se utilizar la funcin f, que utiliza dos parmetros de tipo float y devuelve el resultado del tipo float. */ LLAMAR UNA FUNCIN
Mientras una funcin es definida y su prototipo declarado, se puede utilizar en culquier parte de programa. Sin embargo, como la funcinmain es 'raiz' del programa, no puede ser llamada de ninguna parte de programa. Para ejecutar una funcin, es necesario escribir su nombre y los parmetros asociados. Vea los siguientes ejemplos:

float resultado,a,b; // resultado,a,b,time deben coincidir con los tipos // definidos int time = 100; // en la declaracin de las funciones f y wait_1 a = 10.54; b = 5.2; resultado = f(a,b); // Ejecutar la funcin f por medio de los parmetros a y b // variable resultado pausa_1(tiempo); la variable tiempo funcinX(); parmetros) El valor devuelto se le asigna a la

// Ejecutar la funcin pausa_1 por medio de // Ejecutar la funcin funcinX (sin

Cuando se llama una funcin, el programa salta a la funcin llamada, la ejecuta, despus vuelve a la lnea desde la que fue llamada.

PASAR LOS PARMETROS


Al llamar una funcin, se le pasan los parmetros. En C existen dos formas diferentes para pasar parmetros a una funcin.

El primer mtodo, denominado paso por valor, es el ms fcil. En este caso, los parmetros se pueden considerar como variables locales de la funcin. Cuando se llama una funcin, el valor de cada parmetro se copia a un nuevo espacio de memoria reservado durante la ejecucin de la funcin. Como los parmetros se

39

consideran como variables locales por el compilador, sus valores pueden ser modificados dentro de la funcin, pero sus modificaciones no se quedan en la memoria una vez completada la ejecucin de la funcin.

Tenga en cuenta de que la funcin devuelve un valor, y no una variable. Adems, se crean copias de los valores de los parmetros, por lo que sus nombres en la funcin f pueden ser diferentes de los parmetros utilizados en la main(). La mayor desventaja del paso por el valor es que la nica interaccin que una funcin tiene con el resto del programa es el valor devuelto de un solo resultado (o la modificacin de las variables globales). El otro mtodo, denominado 'paso por direccin' le permite sobrepasar este problema. En vez de enviar el valor de una variable al llamar a funcin, se debe enviar la direccin de memoria del valor. Entonces, la funcin llamada ser capaz de modificar el contenido de esta localidad de memoria.

// Funcin 'sort'ordena los miembros de ascendente // y devuelve el miembro con mximo valor

la

matriz

por

valor

int sort(int *); // Prototipo de funcin const SIZE = 5; // Nmero de miembros a ordenar void main() { int maximum, input[SIZE] = {5,10,3,12,0}; // Declaracin de variables en la matriz maximum = sort(input); // Llamar a funcin y asignarle el mximo // valor a la variable maximum } int sort(int *sequence) { int i, temp, permut; permut = 1; hecho una permutacin // Declaracin de variables // Bandera de bit indica que se ha

while(permut!=0) { // Quedarse en el bucle hasta reinicar la bandera permut = 0; // Bandera reiniciada for(i=0;i<SIZE-1;i++) { // Comparar y oredenar los miembros de la // matriz (dos a dos) if(sequence [i] > sequence[i+1]){ temp = sequence [i]; sequence[i] = sequence[i+1]; sequence[i+1] = temp; permut = 1; // Se ha hecho una permutacin, bandera de bit //se pone a uno } 40

} } return miembro sequence[SIZE-1]; // Devolver el valor del ltimo

} // que es al mismo tiempo el miembro con el mximo valor


En este ejemplo, por medio de una funcin se realizan dos operaciones: ordena los miembros de la matriz por valor asdendente y devuelve el mximo valor.

Para utilizar una matriz en una funcin es necesario asignar la direccin a la matriz (o a su primer miembro). Vea el siguiente ejemplo:

float mtodo_1(int[]); funcin Mtodo_1 float mtodo_2(int*); funcin Mtodo_2

// Declaracin de prototipo de la // Declaracin de prototipo de la

const NMERO_DE_MEDICIONES = 7; // Nmero de los miembros de la matriz void main() { double promedio1, promedio2; // Declaracin de las variables promedio1 // y promedio2 int voltaje [NMERO_DE_MEDICIONES] = {7,8,3,5,6,1,9}; // Declaracin de la // matriz voltaje promedio1 = mtodo_1(&voltaje[0]); // Parmetro de la funcin es la direccin // del primer miembro promedio2 = mtodo_2(voltaje); // Parmetro de la funcin es la direccin de // la matriz } // float mtodo_1(int voltaje[]) // Inicio de la funcin mtodo_1 { int i, suma; // Declaracin de las variables locales i y suma

41

for(i=0;i<NMERO_DE_MEDICIONES;i++) promedio de voltaje suma += voltaje[i]; *(voltaje+i)en vez de voltaje[i] return(suma/NMERO_DE_MEDICIONES); }

//

Clculo

del

valor

// Es posible utilizar

// float mtodo_2 (int *voltaje) //Inicio de la funcin mtodo_2 { int i, suma; // Declaracin de las variables locales i y suma for(i=0;i<NMERO_DE_MEDICIONES;i++) promedio de voltaje suma += *(voltaje+i); voltaje[i] en vez de *(voltaje+i) return(suma/NMERO_DE_MEDICIONES); }
Las funciones 'mtodo_1' y 'mtodo_2' son completamente equivalentes. Las dos devuelven el valor promedio de la matriz 'voltaje[]'. Despus de declararla, la direccin del primer miembro se puede escribir como 'voltaje' o '&voltaje[0]'.

//

Clculo

del

valor

// Es posible utilizar

42

You might also like