Manual basico de_lenguje_c

51
ESCUELA POLITECNICA NACIONAL FACULTAD DE INGENIERIA DE SISTEMAS MANUAL DE LENGUAJE C

Transcript of Manual basico de_lenguje_c

Page 1: Manual basico de_lenguje_c

ESCUELA POLITECNICA NACIONAL

FACULTAD DE INGENIERIA DE SISTEMAS

MANUAL DE LENGUAJE C

Page 2: Manual basico de_lenguje_c

TABLA DE CONTENIDOS CAPITULO I TIPOS DE DATOS Representación de los tipos de datos Caracteres Enteros Los flotantes Tipo de dato void Caracteres con barra invertida CAPITULO II OPERADORES Operadores aritméticos Operadores de comparación Operadores lógicos Operadores a nivel de bits El operador ? Operadores de asignación La coma como operador Operadores de incremento y decremento Operadores de puntero * y & Operador en tiempo de compilación sizeof Los operadores de punto y flecha Los paréntesis y los corchetes como operadores Resumen de precedencias CAPITULO III TIPOS DE DATOS DERIVADOS Arreglos Variables de tipos puntero CAPITULO IV EVALUACION DE EXPRESIONES y ASIGNACION DINAMICA DE MEMORIA Evaluación de expresiones Asignación dinámica de memoria

Page 3: Manual basico de_lenguje_c

CAPITULO V VARIABLES Variables locales Parámetros formales Variables globales Clases de almacenamiento Inicialización de variables CAPITULO VI SENTENCIAS DE CONTROL Valores true y false La sentencia while La sentencia do-while La sentencia for La sentencia if-else La sentencia switch La sentencia break La sentencia continue La sentencia exit La sentencia goto CAPITULO VII INTRODUCCION A LA PROGRAMACION ORIENTADA A OBJETOS Generalización vs especialización Funcionalidad propuesta

Page 4: Manual basico de_lenguje_c

GENERALIDADES

Una de las características fundamentales que se busca actualmente en un lenguaje de programación es que sea portable, esto es, que un programa elaborado en una máquina con características propias pueda ser corrido, realizando mínimas correcciones en otra máquina diferente. La estrategia de portabilidad es bastante importante ya que nos ayuda a mantener nuestros programas, a través de múltiples plataformas hardware. Esta estrategia influye directamente en decisiones económicas y sociales, puesto que nos ahorra un cambio brusco en la concepción de un lenguaje por parte de los programa-dores que pasan a través de diferentes generaciones de lenguajes. Pero C no se queda ahí, actualmente es el lenguaje universal, y su universalidad se debe bastante a la gran acojida mundial que a tenido el sistema operativo UNIX, el cual incluye en su conjunto de herramientas básicas al compilador C. En un principio, al igual que otros lenguajes, no existía un conjunto de estándares definidos para C. Pero en 1983, el insti-tuto de estándares americano ANSI definió los estándares de C. De esta manera, todos los compiladores principales de C ya han implementado el estándar ANSI. Ahora, las grandes casas de hardware ofrecen al cliente como una buena estrategia de venta, la capacidad de poder correr un compilador C que cumpla con los estándares dados por el instituto ANSI. Hace pocos años C pasó a ser el núcleo de lo que hoy es el lenguaje C++, por lo que C++ es ahora un superconjunto de C. Esta inclusión es una gran ventaja para los programadores que trabajan en C y que están introduciéndose a la programación orientada a objetos ofrecida por C++.

Page 5: Manual basico de_lenguje_c

1

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

INTRODUCCION Cero es un punto de partida en C, pues C usa cero para indicar falso, sus arrays comienzan con cero, y cero es el valor de retorno de una operación exitosa en una función. C es poderoso debido a la cuidadosa inclusión de las estructuras correctas de control y los tipos de datos. Es un lenguaje que tiene un conjunto compacto de palabras reservadas. C no es un lenguaje fuertemente estructurado, en el sentido de Pascal y Algol 68, y esto se puede observar en la imposibilidad de inclusión de funciones anidadas. Es relativamente flexible en la conversión de datos, aunque no realice conversión automática de tipos de datos con la facilidad de PL/I. C es un lenguaje de propósito general, pero que no ofrece multi-programación, paralelismo, sincronización, o programación para sistemas especiales; para estos propósitos existen compiladores C con estas características particulares. C es un lenguaje de programación de empleo general, siendo considerado como un lenguaje de "bajo nivel" relativo, esto significa que C trabaja con la misma clase de objetos que la mayoría de las computadoras: caracteres, números y direcciones, que pueden ser combinados con los operadores aritméticos y lógicos, utilizados normalmente en las máquinas. C no contiene funciones para trabajar directamente con elementos como por ejemplo funciones de entrada-salida: No existen proposi-ciones implícitas "READ" o "WRITE" como las que existen en el lenguaje Pascal, ni métodos propios para el acceso a archivos. Todos estos mecanismos de alto nivel deben ser aportados por funciones llamadas explícitamente. Un programa realizado en C, cualquiera que sea su tamaño, consta de una o más "funciones" que especifican las operaciones de cálculo que han de realizarse. Las funciones de C son similares a las funciones y subrutinas de otros lenguajes de programación. La palabra "main" identifica el nombre de la función principal que siempre debe existir si se desea ejecutar un programa y las instrucciones contenidas entre llaves ('{' y '}') especifican el

Page 6: Manual basico de_lenguje_c

2

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

cuerpo de la función; estas instrucciones se cumplen en forma secuencial, el momento en que se invoca el nombre de la función que las contiene. La función "main" es inmediatamente ejecutada al correr el programa ya compilado:

Page 7: Manual basico de_lenguje_c

3

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

CAPITULO I TIPOS DE DATOS 1.1 REPRESENTACION DE LOS TIPOS DE DATOS. El lenguaje de programación C tiene una serie de datos básicos los mismos que siempre estarán guardados en una serie de bits. Por ejemplo un caracter (char en C) se guarda en un byte (8 bits). El almacenamiento depende del tipo de máquina con el que trabajamos, generalmente son máquinas de 16 bits o de 32 bits. En la siguiente tabla se tiene estos tipos de datos: ╔═══════════════════════════════════════════════╗ ║ maquinas de ║ ║tipo representa a 16 bits 32 bits║ ╟───────────────────────────────────────────────╢ ║char caracteres 8 8 ║ ║int enteros 16 32 ║ ║short enteros cortos 16 16 ║ ║long enteros largos 32 32 ║ ║unsigned enteros sin signo 16 32 ║ ║float flotantes 32 32 ║ ║double flotante doble 64 64 ║ ║ precisi≤n ║ ║void generico 0 0 ║ ╚═══════════════════════════════════════════════╝ 1.2 LOS CARACTERES Los caracteres se guardan en ocho bits, o un byte, enumerados de la manera inversa como se presenta a continuación: 7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ la representación de "a" (0x61) en binario es: ┌─┬─┬─┬─┬─┬─┬─┬─┐ │0│1│1│0│0│0│0│1│ └─┴─┴─┴─┴─┴─┴─┴─┘

Page 8: Manual basico de_lenguje_c

4

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

Los caracteres representan todos los dados en el código ASCII, hoy en día se hace uso del ASCII EXTENDIDO, que se guarda en 8 bits, del bit 0 al bit 7. Con el código ASCII extendido se puede representar un total de 256 caracteres, que van desde el 0 al 255. Este código representa a caracteres de control, del 0 al 31, a caracteres tipográficos como las letras mayúsculas, las minús-culas, los dígitos, símbolos, etc. La representación del código ASCII generalmente hace referencia a sus caracteres, por ejemplo, el alfabeto, tiene los caracteres de la "a" a la "z", la letra "a" tiene el código decimal 97, que en hexadecimal es 0x61. Esto permite operaciones como suma, resta, etc., por ejemplo "a" + 1 equivale a 97 + 1 que da como resultado "b". "5" - "0" equivale a restar 53 - 48 lo que nos da el código 5 (un caracter de control). 1.3 LOS ENTEROS De acuerdo a su alcance tienen diferentes formas de representación en C: 1.3.1 Enteros (int). Estos se guardan en 1 palabra (dos bytes), el bit más significativo (el 15) es de signo (0 positivo, 1 negativo), los otros 15 bits (del 0 al 14) son bits de datos: ┌──┬──┬──┬──┬──┬──┬──┬──┐ ┌──┬──┬──┬──┬──┬──┬──┬──┐ │15│14│13│12│11│10│ 9│ 8│ │ 7│ 6│ 5│ 4│ 3│ 2│ 1│ 0│ └──┴──┴──┴──┴──┴──┴──┴──┘ └──┴──┴──┴──┴──┴──┴──┴──┘ el rango de valores que se puede contener un entero es: -215 <= entero <= 215 - 1 que es lo mismo que: -32768 <= entero <= 32767 Esta representación es para compiladores de 16 bits. Para compi-ladores de 32 bits como Watcom C, se tiene un bit de signo, el 31, y 31 bits de datos, del 0 al 30, lo que da un rango de valores: -231 <= entero <= 231 - 1

Page 9: Manual basico de_lenguje_c

5

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

1.3.2 Enteros cortos (short). Para compiladores de 16 bits y 32 bits, un entero corto coincide con la definición y rango dado para enteros (int). 1.3.3 Enteros Largos (long).- Para máquinas de 16 y 32 bits los enteros largos se almacenan en 4 bytes, igualmente el bit más significativo (el 31) será el bit de signo, mientras que los 31 restantes serán de datos (del 0 al 30), con lo que tenemos un rango de valores entre -231 y 231-1. 1.3.4 Enteros sin signo (unsigned).- Para máquinas de 16 bits los enteros sin signo se almacenan en 2 bytes, y para máquinas de 32 bits se almacenan en 4 bytes. Como su nombre lo dice, no se toma en cuenta el bit de signo, es decir que todos los bits son de datos, con esto tenemos un rango de valores entre 0 y 216 para máquinas de 16 bits, y entre 0 y 232 para máquinas de 32 bits. 1.4 LOS FLOTANTES Los valores de punto flotante se refieren a aquellos en que deben estar presentes el punto decimal, y expontes con base 10, que son los números reales como por ejemplo: 1.3456 3.14657 0.8754 1.2e-34 1.2e-20 representa a 0.12*10-19

El rango de valores que puede tomar el tipo flotante, está entre 10-37 y 10+37. Los números de punto flotante (float y double) representan internamente a la mantiza, que es la parte fracciona-ria, y al exponente. Para el último ejemplo, en la mantiza encontramos el valor 12 (la parte fraccionaria) y el exponente es -19. Tanto float como double tienen el mismo rango de valores, sin embargo double da una mayor precisión en la mantiza, teniendo hasta diez dígitos de precisión frente a seis dados por float A continuación se indica una tabla con los tipos de datos básicos: Tipo Tamaño(bits) Rango

Page 10: Manual basico de_lenguje_c

6

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

────────────────────────────────────────────────────────────── char 8 bits -128 a 127 int 32 -32768 a 32767 unsigned int 16 0 a 65535 long int 32 -2,147,483,648 a -2,147,483,647 float 32 seis dígitos de precisión double 64 diez dígitos de precisión long double 128 diez dígitos de precisión ────────────────────────────────────────────────────────────── El diagrama que se muestra a continuación representa las formas en que podemos combinar los tipos de datos elementales con las respectivas extensiones para obtener nuevos tipos de datos; por ejemplo el grupo de enteros está conformado por el tipo de dato elemental int y también por unsigned int, short int y long int. tipo elemental >─┐ ├───────────────────────┬──────char ├───unsigned──────>─────┘ ├───────────────────────┬───────int │ │ ├──────────short──────>─┤ │ │ ├──────────unsigned───>─┤ │ │ ├──────────long───────>─┘ │ ├───────────────────────────────float ├────────────────────────┬──────double └──────────long───────>──┘ 1.5 TIPO DE DATO VOID Es tipo de dato void no especifica un tipo de dato fijo, sino que puede adaptarse a cualquier tipo dada una circunstancia específi-ca. Veamos algunas declaraciones de variables y funciones tipo void: void *p; Indica que p es un puntero genérico, nos es útil para guardar en memoria objetos cuyos tipos de datos nos sean descono-cidos.

Page 11: Manual basico de_lenguje_c

7

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

void fun1(); es una función que no retornará ningún valor, por ejemplo, en "dos.h" existe la función clrscr(), que se limita a borrar todo lo que esté en pantalla, esta función realizará esta tarea sin necesidad de retornar valor alguno. int fun2(void); indica que no se requiere colocar argumentos de entrada, como por ejemplo una función para obtener la fecha del sistema, date(), no se requiere de argumento alguno. void *fun3(); esta función devolverá un puntero genérico, se lo estudiará detenidamente cuando se revise las funciones malloc y calloc. 1.6 CARACTERES CON BARRA INVERTIDA El incluír entre comillas los carateres es suficiente para imprimir en pantalla una salida, por ejemplo la siguiente cadena de caracteres: "hola, mundo", sin embargo es necesario que se pueda incluír dentro de esta cadena de caracteres, algunos controles, es por ello que C dentro de cadenas nos permite utilizar códigos de control por medio de la barra invertida \. Por ejemplo, al imprimir el mensaje enterior, si queremos que haya un salto de línea (nueva línea) luego de la impresión, el formato de la cadena sería: "hola, mundo \n", donde \n es el orden de salto de línea. Veamos una tabla de códigos de barra invertida: codigo significado ──────────────────────────────────── \b espacio atrás \f salto de página \n salto de línea \r salto de carro \t tabulación horizontal \" imprime comillas \' imprime comilla simple \0 caracter nulo \\ imprime barra invertida \v tabulación vertical \a alerta \o constante octal \x constante hexadecimal ────────────────────────────────────

Page 12: Manual basico de_lenguje_c

8

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

La manera de representar el caracter nulo es \0, en realidad podemos extendernos para que \### sea la impresión del caracter cuyo código ASCII esté dado por ###, por ejemplo para obtener un sonido de la computadora \007.

Page 13: Manual basico de_lenguje_c

9

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

CAPITULO II OPERADORES Una de las mejores características de C es la cantidad de opera-dores que posee y los diversos niveles en los que actúa: 2.1 OPERADORES ARITMETICOS Se tienen los siguientes operadores aritméticos ya conocidos en otros lenguajes: + operador binario de suma - operador binario de resta * operador binario de multiplicación / operador binario de división % operador binario de resto de división El operador - se lo puede utilizar también como operador unario que hace negativo a un número. Generalmente casi todos estos operadores nos permiten realizar las operaciones aritméticas básicas, adicionalmente se tiene el operador % que es el resto de una división, por ejemplo, la respuesta a la operación 7%4 es 3 (entero), el resultado de 9 % 3 es 0, el de 5 % 2 es 1, 1 % 8 dará 1, etc. 1.2 OPERADORES DE COMPARACION Los operadores binarios de comparación son: > mayor que < menor que == igual que >= mayor o igual que <= menor o igual que != no es igual que Estos operadores compararán dos expresiones, el resultado será un valor entero, 0 si no cumple con la relación de comparación, o 1 si la cumple, por ejemplo si la relación x < y es verdadera, tendremos que se devuelve un valor entero 1, caso contrario, el valor será 0. Veamos algunos ejemplos:

Page 14: Manual basico de_lenguje_c

10

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

si a = 10 y b = 15 entonces ( a < b ), ( a <= b ), ( a != b ) darán todos 1, en cambio que ( a > b ) ( a >= b ) y ( a == b ) darán todos 0. 1.3 OPERADORES LOGICOS Los operadores lógicos son: ! es la negación (operador unario) && es el operador binario lógico de intersección (and) || es la operador binario lógico de unión (or) El operador ! invierte el resultado de una expresión cuando ha sido verdadera o falsa. Para los ejemplos anteriores tendremos que !( a > b ) dará un 1 y !( a < b ) dará un 0. Veamos las tablas de funcionamiento (o tablas de verdad) de la intersección (&&) y unión (||): && | 0 1 || | 0 1 0 | 0 0 0 | 0 1 1 | 0 1 1 | 1 1 se puede realizar operaciones mas complejas entre relaciones como: (( a > b ) && !(1 == 2)) || (b == a) ((0) && !(0)) || (0) (0 && 1 ) || 0 0 || 0 0 1.4 OPERADORES A NIVEL DE BITS C soporta un completo juego de operadores a nivel de bits. Dado que el lenguaje se diseño para sustituir al ensamblador en muchas tareas de programación, era importante permitir todas las opera-ciones que se pueden hacer en ensamblador. Estas operaciones se refieren a la comprobación, asignación o desplazamiento de los bits reales que componen un byte o una palabra, que corresponden a los tipos estándar de C char e int. Las operaciones a nivel de bits no se pueden usar sobre otros

Page 15: Manual basico de_lenguje_c

11

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

tipos. La tabla de la siguiente página lista los operadores que se aplican a las operaciones a nivel de bits. Los operadores &, | y ~ a nivel de bits están basados en la misma tabla de verdad que sus equivalentes lógicos, excepto que trabajan bit a bit. Para el caso de XOR, el resultado es verdad si uno y sólo uno de los operandos es verdad Operador Acción & (Y) | (O) ^ (XOR) ~ Complemento a uno (NOT) >> Desplazamiento a la derecha << Desplazamiento a la izquierda Como ejemplo, se detalla una función que leerá un caracter del puerto del modem, utilizando la función leer_modem() y pondrá el bit de paridad a cero: char car_del_modem(void) { char c; c = leer_modem(); /*obtener un caracter del puerto del modem */ return( c & 127) } El bit de paridad, el cual se utiliza para indicar que el resto de los bits del byte no han cambiado, utiliza el bit más signifi-cativo de cada byte, que es el octavo bit. Al realizar un AND (Y) entre un byte que tenga los bits de 1 a 7 en uno y el bit ocho en cero y el byte recibido por el modem, la paridad se pone a cero. La expresión c & 127 da como resultado esta operación. En el ejemplo se supone que en c se ha recibido el carácter "A" con el bit de paridad a uno: Bit de paridad │ V 1 1 0 0 0 0 0 1 c conteniendo "A" con paridad a 1

Page 16: Manual basico de_lenguje_c

12

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

0 1 1 1 1 1 1 1 127 en binario &───────────────────── hacer Y a nivel de bits 0 1 0 0 0 0 0 1 "A" sin paridad La operación OR (O) bit a bit siendo la inversa de (Y), pone los bits a uno. Cualquier bit del operando que esté puesto a 1 hace que el correspondiente bit de la variable se ponga a uno. Recuerde que los operadores relacionales y lógicos siempre producen un resultado que es 0 ó 1. Los operadores de desplazamiento >> y <<, mueven todos los bits de una variable a la derecha o a la izquierda según se especifique. La forma general de una sentencia de desplazamiento a la derecha es: variable >> número de posiciones en bits La sentencia de desplazamiento a la izquierda es: variable << número de posiciones en bits A medida que se desplazan los bits hacia un extremo se va relle-nando con ceros por el extremo opuesto, recuerde que un desplaza-miento no es una rotación, es decir que los bits que salen por el un extremo no ingresan al otro. Las operaciones de desplazamiento de bits pueden ser muy útiles cuando se decodifica la entrada a través de dispositivos externos, como los convertidores D/A, y en la lectura de información de estado. Se pueden utilizar también para operaciones rápidas de multiplicación y división entre enteros. Un desplazamiento a la izquierda equivale a una multiplicación por 2 y uno a la derecha una división por 2 Ejemplo de desplazamiento. #include "stdio.h" { unsigned int i; int j; i = 1;

Page 17: Manual basico de_lenguje_c

13

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

/* desplazamientos a la izquierda */ for (j=0; j<4; j++) { i = i << 1; /* desplazar i a la izquierda en

1, que es lo mismo que multiplicarlo por 2 */

printf("desplazamiento a la izquuierda %d: %d\n",j,i); } } El operador de complemento a uno (~) cambia el estado de cada bit en la variable especificada, es decir, los 1 se ponen a 0 y los 0 a 1. Los operadores a nivel de bits se usan a menudo en rutinas de cifrado. Si se quiere que un archivo parezca ilegible, basta con llevar a cabo en él algunas operaciones a nivel de bits. 1.5 EL OPERADOR ? C contiene un operador muy potente que se usa para sustituir ciertas sentencias en la forma if-then-else. El operador ternario ? toma la forma general: Exp1 ? Exp2 : Exp3 donde Exp1, Exp2 y Exp3 son expresiones. y ? actúa de la siguiente forma: Evalúa Exp1. Si es cierta, evalúa Exp2 y toma ese valor para la expresión, Si Exp1 es falsa, evalúa Exp3 tomando su valor para la expresión. Por ejemplo: x = 10; y = x>9 ? 100 : 200; a y se le asigna el valor de 100. Si x hubiera sido menor que 9, y se habría recibido el valor de 200. Este mismo código escrito con la sentencia if-then-else es: x = 10;

Page 18: Manual basico de_lenguje_c

14

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

if (x>9) y = 100; else y = 200; 1.6 EL OPERADOR DE ASIGNACION Al igual que otros lenguajes, en C las operaciones más básicas se complementan con la sentencia más simple, la de asignación (por ejemplo a = b + c). Sin embargo en C, = es un operador (así como los operadores aritméticos), es decir que a=b+c es una expresión antes que solo una sentencia de asignación. El tener a = como un operador, nos permite tener operaciones complejas tales como: a = b + c = d + 2; equivale a c = d + 2; a = b + c; Igualmente esta característica del igual (=) nos permite que podamos construír operadores compuestos: a = a + b equivale a a += b a = a - b a -= b a = a & 0x0F a &= 0x0F Esta composición de operadores se permite entre los operadores binarios aritméticos y de manipulación de bits ( + - * / & | ^ << >> ). 1.7 LA COMA COMO OPERADOR Como operador, la coma encadena varias expresiones. La parte izquierda del operador coma siempre se evalúa como void. Esto significa que la expresión de la parte derecha se convierte en el valor de la expresión total separada por coma. Por ejemplo: x = (y=3, y+1); primero asigna el valor de 3 a y y luego asigna el valor de 4 a x Los paréntesis son necesarios debido a que el operador coma tiene menor precendencia que el operador de asignación. 1.8 OPERADORES DE INCREMENTO Y DECREMENTO

Page 19: Manual basico de_lenguje_c

15

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

Los operadores de incremento (++) y decremento (--) nos permiten optimizar operaciones de suma o resta en 1 x = x + 1 es igual a x += 1 e igual que ++x o x++ x = x - 1 es igual a x -= 1 e igual que --x o x-- La diferencia entre ++x o x++ es que en el primer caso la variable se incrementa antes de su utilización, en cambio que en el segundo caso, la variable se incrementa luego de su utilización, igual cosa ocurrirá con el decremento. Ejemplo: p[++s] = 2 equivale a s += 1 p[s] = 2 p[++s] = 2 equivale a p[s] = 2 s += 1 1.9 OPERADORES DE PUNTERO & y * Un puntero es la dirección de memoria de una variable. Una variable puntero es una variable específicamente declarada para contener un puntero a su tipo específico. El primer operador de punteros es &, un operador monario que devuelve la dirección de memoria del operando, por ejemplo: m = &cont; coloca en m la dirección de memoria de la variable cont. No tiene nada que ver con el valor de cont. El segundo operador de punteros es * que es complementario de &. Es un operador monario que devuelve el valor de la variable ubicada en la dirección que se especifica. Por ejemplo, si m contiene la dirección de memoria de la variable cont, entonces: q = *m; colocará el valor de cont en q. Las variables que vayan a contener punteros se declararán como tales. Las variables que vayan a mantener direcciones de memoria o punteros, deberán declararse colocando un * delante del nombre

Page 20: Manual basico de_lenguje_c

16

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

de la variable. Esto indica al computador que va a contener un puntero a ese tipo de variable. Por ejemplo, para declarar c como puntero a caracter podemos escribir char *c; Aquí, c no es un caracter, sino un puntero a un caracter. El tipo de dato al que apunta un puntero, en este caso char, se denomina tipo base del puntero, así, un puntero a caracter (o cualquier puntero en general) tiene un tamaño sufuciente para guardar una dirección tal como esté definida por la arquitectura de la computadora que se utilice. 1.10 EL OPERADOR DE TIEMPO DE COMPILACION sizeof El operador sizeof es un operador monario de tiempo de compilación que devuelve la longitud, en bytes, de la variable o del especificador de tipo entre paréntesis al que precede. Por ejemplo, suponiendo que los enteros son de 2 bytes y los float de 8 bytes, entonces float f; printf("%f", sizeof f); printf("%d", sizeof int); mostrará 8 2 Recuerde que para calcular el tamaño de un tipo, el nombre del tipo debe ir entre paréntesis 1.11 LOS OPERADORES PUNTO (.) y FLECHA (->) Estos operadores referencian elementos individuales de las estructuras y de las uniones. Las estructuras y las uniones son tipos de datos compuestos que se pueden referenciar bajo un solo nombre. El operador punto se usa cuando se trabaja realmente con la estructura o la unión, el operador flecha se usa cuando se usa un

Page 21: Manual basico de_lenguje_c

17

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

puntero a una estructura o una unión. Por ejemplo, dada la estructura global: struct empleado { char nombre [80]; int edad; float sueldo; } emp; struct empleado *p = &emp; /* en p, la dirección de emp */ Se escribirá el siguiente código para asignar el valor 123,34 al elemento sueldo de la estructura emp: emp.sueldo = 123.23; Sin embargo, la misma asignación usando un puntero a la estructura emp sería: p->sueldo = 123.23; 1.12 LOS PARENTESIS Y LOS CORCHETES COMO OPERADORES Los paréntesis son operadores que aumentan la precedencia de las operaciones que contienen. Los corchetes llevan a cabo el indexamiento de arrays. Dado un array, la expresión entre corchetes proporciona un índice para el array, como en el ejemplo de la siguiente página, se asigna primero el valor 'X' al cuarto elemento (recuerde que los arrays en C comienzan en el elemento cero) del array c y luego se imprime ese elemento. #include "stdio.h" char c[80]; void main (void)

Page 22: Manual basico de_lenguje_c

18

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

{ c[3] = 'X'; printf("%c", c[3]); } 1.13 RESUMEN DE PRECEDENCIAS La siguiente tabla lista la precedencia de todos los operadores del lenguaje C, Observe que todos los operadores menos los monarios y ?, asocian de izquierda a derecha. Los operadores monarios (*,&,) y el ? asocian de derecha a izquierda. ────────────────────────────────────────────────────────────── Mayor precedencia () [] → . ! ~ ++ -- - (tipo) * & sizeof * / % = - << >> < <= > >= == != & ^ | && || ? = += -= *= /= Menor precedencia , ──────────────────────────────────────────────────────────────

Page 23: Manual basico de_lenguje_c

19

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

CAPITULO III TIPOS DE DATOS DERIVADOS C nos permite construír a partir de datos elementales otros más complejos. Algunos ya los tenemos definidos por el lenguaje, mientras que otros se derivan de los tipos fundamentales. 3.1 ARRAY (ARREGLOS) Son tablas de datos del mismo tipo. Declaración. Se necesitarán de cuatro elementos: * nombre del array * tipo * dimensión o cantidad de elementos que lo componen * clase de almacenamiento en memoria Ejemplos: int tab[100]; En este ejemplo se ha declarado un array de tipo entero de nombre tab que tendrá 100 elementos enteros (tab[0]..tab[99]); el almacenamiento en memoria queda implícito, pues será de tipo externo o automático). static char texto[32]; En este ejemplo, el tipo ya no es implícito, la clases de ubica-ción posibles de una array en memoria son la externa, estática y automática. Un array puede ser considerado como una variable o como un todo. Considerada como un todo, es una colección de variables de un tipo dado, en que cada uno de los elementos de la colección está destinado a contener un valor concreto. Si t es el nombre del array de la tabla entonces: • t[0] es el primer elemento de esta colección.

Page 24: Manual basico de_lenguje_c

20

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

• t[i] es el elemento (i-1)-ésimo de la colección y además es una variable de determinado tipo.

Si en cambio t se considera como un identificador de un todo, el identificador t nos permite señalar la dirección donde comienza el almacenamiento de la tabla. La dirección igual puede obtenerse utilizando el operador & ; es decir &t[0] es lo mismo que t. Si queremos buscar la dirección i entonces podemos obtenerla sea como &t[i] o como t+i. Valores iniciales de los elementos de un array. Si el almacenamiento de memoria para el array es externo o estático, entonces sus valores iniciales también podrán ser declarados en el momento de la compilación. Se deberá especificar los elementos de la lista separados por comas y encerrando la lista entre llaves, quedando por lo tanto opcional la declaración del total de elementos del array que, como en los siguientes ejemplos, se calculará automaticamente: static char letra[] = {'t','e','x','t','o'}; static int digito[] = { 0,1,2,3,4,5,6,7,8,9 }; En caso de haberse especificado el número total de elementos del array, los valores iniciales que se especifican deben estar en un número igual o menor al número total explícito: short pares[5] = { 2,4,6 }; donde: pares[0] = 2 pares[1] = 4 pares[2] = 6 pares[3] = 0 pares[4] = 0 Tablas multidimensionales Para la definición de tablas multidimensionales solo necesitamos juntar los operadores [] que sean necesarios. En el siguiente ejemplo tenemos una tabla de 10 tablas de 20 enteros cada una: int t2d[10][20] ; Además se comporta como una tabla bidimensional donde 10 es el número de líneas y 20 el número de columnas. El acceso a un

Page 25: Manual basico de_lenguje_c

21

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

elemento se obtiene con los índices internos, los mismos que deben variar entre 0 y la dimensión menos 1. Si queremos inicializar una tabla multidimensional procedemos de la misma manera como se explicitó anteriormente: long t2d [5][4] = { { 0,1,2,3 } /* t2d[0][] */ { 4,5,6,7 } /* t2d[1][] */ { 8,9,10,11 } /* t2d[2][] */ } ; int t3d [2][2][2] = {{ { 1,2 } /* t3d[0][0][] */ { 3,4 } /* t3d[0][1][] */ } { { 5,6 } /* t3d[1][0][] */ { 7,8 } /* t3d[1][1][] */ }} ; El siguiente ejemplo, en cambio inicializa la primera columna a 1: int tab[3][2] = {{1},{1},{1}} ; /* fig.1 */ y tiene un comportamiento diferente a: int tab[3][2] = { 1,1,1 } ; /* fig.2 */ fig.1 fig.2 1 | 0 1 | 1 1 | 0 1 | 0 1 | 0 0 | 0 3.2 VARIABLES DE TIPOS PUNTERO (POINTER) Un puntero (pointer) es una dirección de memoria en cuya localidad está almacenado un valor correspondiente a un dato. Para el manejo de punteros en C se tienen dos operadores: & se refiere a la dirección de un dato.

Page 26: Manual basico de_lenguje_c

22

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

* se refiere al contenido de un dato. Declaración Es necesario que una variable de tipo puntero señale a algún tipo definido: int *ptri ; /* ptri es un puntero a un número entero */ El operador de tipo puntero * puede solo aplicarse a expresiones de tipo puntero. El momento de declarar, no se tiene todavía en claro a qué objeto apuntar, pues se conoce únicamente su tipo, es por ello que también se permite dar un valor inicial. En el siguiente ejemplo: int i, *p, t[100] ; la variable i está declarada como entero, p como un puntero a un entero, y t un array de 100 enteros. Serán correctas las siguien-tes instrucciones de asignación: p = &i ; /* p apunta al entero i */ *p = 0 ; /* el valor 0 es asignado a i */ Para la puesta a 0 de todos los elementos de la tabla t: for (i=0 ; i<99 ; i++ ) t[i]=0; también puede hacerse de las siguiente manera utilizando el puntero: for ( p=&t[0] ; p < &t[100] ; p++ ) *p=0 ; o también: for ( p=t ; p < t+100 ; p++ ) *p=0 ; Operaciones con punteros Existe una forma equivalente de lograr las direcciones de un array, tomando en cuenta la última declaración del array t[100] de 100 enteros:

Page 27: Manual basico de_lenguje_c

23

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

t es equivalente a &t[0] t+i es equivalente a &t[i] t[i] es equivalente a *(t+i) Es por ello que se permiten operaciones como p++ y t+100. Una constante no puede ser asignada como valor a una variable, salvo en el caso de cero: p = 0 ; /* puntero vacío */ En tal caso el puntero no apunta a ningún lado. En cambio la adición o substracción (como ya se vio) del valor de una variable o constante entera son operaciones válidas: p++ (que es lo mismo que p=p+1), y añade 2 al valor actual de p, ya que p señala a un entero en memoria (un entero se almacena en 2 bytes), la operación p++ debe señalar al entero siguiente. Si se ubiera declarado como un puntero a double, entonces se añadiría 8 al valor actual de p. Otras operaciones como p-=2 y p+=(i+5) también son correctas. Esto indica que el valor añadido es convertido en múltiplo del tamaño del objeto al cual señala el puntero afectado por opera-ciones de incremento o decremento. Las otras operaciones aritmé-ticas y lógicas no están permitidas. ( * / % & | ^ ~ ). Operacio-nes como: int *p, *q ; p = 1; q = 2; if (p < q); .... son inválidas ya que en este caso se realiza una operación de comparación con punteros.

Page 28: Manual basico de_lenguje_c

24

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

CAPITULO IV EVALUACION DE EXPRESIONES y

ASIGNACION DINAMICA DE MEMORIA 4.1 EVALUACION DE EXPRESIONES Para el estudio de evaluación de expresiones en C, primero debemos observar las prioridades de los operadores, las mismas que se dan en el siguiente cuadro, donde los operadores () [] -> . son de máxima prioridad mientras que el de menor prioridad será el operador coma. ┌────────────────────────────────────────────────┬───────────┐ │ () [] -> . │ izq. a der│ │ ! ~ ++ -- - * & (TIPO) sizeof │ der. a izq│ │ * / % │ izq. a der│ │ + - │ izq. a der│ │ << >> │ izq. a der│ │ < <= > >= │ izq. a der│ │ == != │ izq. a der│ │ & │ izq. a der│ │ ^ │ izq. a der│ │ | │ izq. a der│ │ && │ izq. a der│ │ || │ izq. a der│ │ ? | │ izq. a der│ │ = += -= *= /= %= >>= <<= &= |= ^= │ der. a izq│ │ , │ izq. a der│ └────────────────────────────────────────────────┴───────────┘ La primera consideración a tomar en cuenta para la evaluación de expresiones es que las expresiones (que no sean de asignación) se evalúan de izquierda a derecha, tomando en cuenta la tabla de prioridad de operadores, por ejemplo: a + b * c es equivalenta a a + (b * c) b / c + b * c es equivalente a (b / c) + (b * c)

Page 29: Manual basico de_lenguje_c

25

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

La segunda consideración, para los operadores unarios y de asignación, la evaluación va de derecha a izquierda. Por ejemplo en la siguiente asignación: a = a / d + b * c; primero se evalua la a /d luego b * c, seguimos con la suma de estas dos expresiones evaluadas, y por último, luego de haber evaluado la expresión de la derecha procedemos a la asignación. Para el caso de asignaciones múltiples, la evaluación será de derecha a izquierda, en el siguiente ejemplo, primero se evaluará a + b cuyo resultado se asigna a k, el valor asignado a k se asigna luego a j, y este valor se asigna por último a i. i = j = k = a + b; Veamos otros ejemplos: x = x + b * c; es equivalenta a x += b * c; x = x * (b + c); es equivalente a x *= b + c; x = x * b + c; es equivalente a x = (x * b) + c; 4.2 ASIGNACIÓN DINAMICA DE MEMORIA Un aspecto importante de C es la signación dinámica de memoria que se necesitan para algunos casos. Por ejemplo, cuando declaramos una variable tipo entero, y un punetero a entero: int a; /* a variable entera */ int *pa; /* pa es un puntero a un entero */ En el primer caso, para la variable entera a, no es necesario que el programador cree el espacio donde se guardará el valor asignado a tal variable, el espacio está creado. Para el segundo caso, el del puntero a entero *pa, en cambio tenemos dos opciones: a) Como el puntero es una dirección a un objeto específico,

entonces tenemos la opción de que el puntero apunte a una dirección donde esté un entero, en este caso es a:

pa = &a ; /* &a quiere decir la dirección de a */

Page 30: Manual basico de_lenguje_c

26

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

b) La segunda opción es crear el espacio donde se guarde el

valor apuntado por pa. Para esto C nos proporciona tres funciones: calloc, malloc y realloc. Si con estas tres funciones se nos permite la reserva de espacios de memoria, también debemos tener capacidad de liberar espacios de memoria, esto lo haremos con la funsión free.

Estas cuatro funciones (malloc, calloc, realloc y free) se encuentran en la librería stdlib.h. 4.2.1 La función malloc() #include "stdlib.h" void *malloc(tam); unsigned int tam; Supongamos que se requiere reservar memoria para guardar un número entero, el mismo que será señalado por pa, el formato para realizar dicha operación de reserva de memoria es el siguiente: pa = (int *)malloc(sizeof(int)) ; entonces se puede realizar operaciones de asignación como la siguiente: *pa = 5;. Esta operación no es posible realizar sin la reserva de memoria previa. La operación de reserva de memoria puede ser generalizada como sigue: ptr = (tipo *)malloc(sizeof(tipo)) ; En realidad, esta operación puede resultar confusa, sería natural que se reserve memoria de longitud dada solamente de la siguiente manera: ptr = malloc(sizeof(tipo)) ; Lo que pasa es que malloc() reserva memoria contínua de longitud dada por sizeof(tipo), lo que devuelve es un puntero a void, (puntero genérico). Esto implica que (tipo *) hace un casting (conversión de tipo) para adaptar la reserva de memoria al tipo de puntero correcto.

Page 31: Manual basico de_lenguje_c

27

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

La expresión (tipo *)malloc(sizeof(tipo)) puede ser llamada en forma más simple si declaramos una macro como la que sigue: #define MALLOC(x) ((x*)malloc(sizeof(x))) ; De esta manera la operación de reserva para la variable ap sería: ap = MALLOC(int) ; 4.2.2 La función calloc() #include "stdlib.h" void *calloc(num,tam); unsigned int num; unsigned int tam; calloc(), se caracteriza porque guarda una serie de espacios, cada uno de los cuales tiene una longitud dada, además que estos valores reservados son inicializados con ceros. Para la utilización de calloc debemos conocer dos informaciones, la primera sobre el número de elementos (n), y la segunda sobre la longitud del tipo de elemento (sizeof(tipo)). Como la función sigue entregando un puntero a void es necesario seguir utilizando el casting. Por tanto el formato es el siguiente: ptr = (tipo *)calloc(n,sizeof(tipo)) ; Así mismo es posible, que por medio de una macro, simplificar la llamada a esta función, la macro podría ser: #define CALLOC(n,x) ( (x *)calloc(n,sizeof(x)) ) ; Para nuestro ejemplo podríamos concluír una equivalencia: ap = MALLOC(int) ; es equivalente a ap = CALLOC(1,int) ; 4.2.3 Punetros Nulos (NULL) A los punteros no les podemos asignar valores como:

Page 32: Manual basico de_lenguje_c

28

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

ap = 21 ; /* asignación incorrecta */ En cambio es posible asignarle un valor cero, esto significa que el puntero no señala a ninguna parte: ap = 0 ; es equivalente a ap = NULL ; NULL es una constante predefinida para punteros, que indica dirección nula. Este valor resulta cuando fracasa el llamado a las funciones malloc y calloc, generalmente cuando se solicita más memoria de la disponible, por ejemplo, en la siguiente expresión: ap = MALLOC(int) ; Si la memoria disponible es menor a la solicitada entonces ap señalará a NULL. 4.2.4 Liberación de Bloques de Memoria (free) #include "stdlib.h" void *free(ptr); void ptr; De la misma manera como reservamos memoria es también necesario liberarla, pues si hemos asignado memoria en forma dinámica, cuando retiremos la referencia a ese espacio, se mantendrá y no estará disponible, es decir se ha convertido en basura. Si no vamos a seguir utilizando ese espacio de memoria entonces debemos liberarlo, esto lo conseguiremos con la función free, cuyo formato es: free(ptr); 4.2.5 realloc() #include "stdlib.h"

Page 33: Manual basico de_lenguje_c

29

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

void *realloc(ptr,tam); void *ptr; unsigned int tam; Esta función cambia el tamaño de la memoria apuntada por ptr. La longitud del nuevo tamaño está especificada por tam, pudiendo tomar valores mayores o menores al anteriormente asignado.

Page 34: Manual basico de_lenguje_c

30

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

CAPITULO V VARIABLES Las variables son posiciones en memoria representados por identi-ficadores que almacenan valores de un tipo determinado, y cuyo tiempo de vida y modo de almacenamiento está determinado por dónde y cómo se declaren. Un programa en C, el momento de correrse tiene el siguiente mapa de memoria: ┌─────────────┐ │ │ direcciones de retorno de funciones, estado del │ pila │ CPU, variables locales (automßticas). ├─────────────┤ │ monton │ se utiliza para la asignaci≤n dinßmica de │ (heap) │ memoria (manejo de punteros). ├─────────────┤ │ variables │ │ globales │ ├─────────────┤ │ c≤digo del │ │ programa │ └─────────────┘ Los identificadores se componen de letras (A, B, .. , Z, a, b, .. , z) y dígitos (0,1,..9), pero siempre deben comenzar con una letra o subrayado. C diferencia las letras mayúsculas de las minúsculas, es decir que el identificador de función malloc() es diferente a MALLOC(). La declaración de una variable tiene la siguiente forma: <clase> <tipo> <lista de identificadores> ; Por ejemplo: auto int i,j,k; float fi,fj,fk;

Page 35: Manual basico de_lenguje_c

31

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

Primeramente hemos definido las variables i,j,k, todas ellas de tipo entero y cuya clase es automática. En el segundo caso se ha declarado la lista de variables fi,fj,fk de tipo float, quedando explícita la clase. Según donde se declare una variables, éstas puenen ser: 1) Variables locales (dentro de funciones). 2) Parámetros formales (argumentos de funciones). 3) Variables Globales (fuera de funciones). 5.1 VARIABLES LOCALES Son todas las variables que se declaran dentro de una función. Su tiempo de vida es el tiempo que dure la ejecución de dicha función, luego de lo cual se destruye. Esto, en cuanto a funcio-nes, pero también son locales las variables que se crean dentro de bloques (un bloque queda delimitado por { }). Veamos dos ejemplos: ┌─────────────┐ ┌───────────────────┐ │ en funci≤n: │ │en bloque: │ │ │ │ │ │ func1() │ │... │ │ { │ │if (condicion) │ │ int x ; │ │ { │ │ ... │ │ int array[20] ; │ │ } │ │ ... │ │ │ │ } │ │ func2() │ └───────────────────┘ │ { │ fig. 2 │ int x ; │ │ ... │ │ } │ fig. 1 └─────────────┘ En el caso de la figura 1, tenemos dos funciones, en ambas se declara una variable x, la variable x de func1 nada tiene que ver con la variable x de func2, son totalmente independientes. Para

Page 36: Manual basico de_lenguje_c

32

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

el caso de la figura 2 tenemos una declaración dentro de un bloque, int array[20]; esta variable local se creará en forma automática si y solo si se ejecuta el respectivo bloque, si hacemos referencia a esta variable fuera del bloque, entonces obtendremos un error. Las variables locales también pueden declararse como: auto int x; pero esto es innecesario, pues toda variable que no es global es local o automática, es por ello que la palabra reservada auto, que significa automática, local, casi no es utilizada. Hemos dicho que una variable local está creada mientras dura la ejecución de la función donde se las declara, esto impide que se las pueda inicializar en tiempo de compilación, es por ello que si queremos inicializar o mantener su valor sin que se destruya, podemos declararlas con la palabra reservada static: static int x = 5 ; static float fx ; Esto implica que durante la ejecución del programa se va a mentener el espacio en memoria para las variables estáticas en lugar de crearse o destruírse automáticamente, pero el acceso a ellas es solo por medio de las funciones donde se las declare. 5.2 PARAMETROS FORMALES Los parámetros formales son los argumentos de una función, si es que una función tiene argumentos como en el siguiente caso: int suma(a,b); int a,b; { return (a+b); }

Page 37: Manual basico de_lenguje_c

33

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

En este ejemplo los parámetros formales son a y b, sus tipos son declarados luego de la declaración de la función. 5.3 VARIABLES GLOBALES Las variables globales se mantienen durante todo el programa y pueden ser llamadas y cambiadas en cualquier parte de él (como las variables en BASIC), la declaración de una variable global debe hacerse desde fuera de las funciones, por ejemplo: int cuenta; /* cuenta es variable global */ main() { ... cuenta = 100 ; func() ; /* el valor de cuenta ahora es de 101 */ ... } func() { ... ++cuenta; /* cuenta adquire un nuevo valor (101)*/ ... } 5.4 CLASES DE ALMACENAMIENTO Existen 4 clases de almacenamiento en memoria para las variables: extern, static, register, auto, las que a continuación son descritas. 5.4.1 extern

Page 38: Manual basico de_lenguje_c

34

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

Cuando tenemos varios módulos de programación, y necesitamos en determinado módulo utilizar variables globales que fueron decla-radas en otro, debemos volver a declarar las mismas variables pero de clase extern. Supongamos que en el módulo princip.c tenemos las siguientes declaraciones: princip.c int cuenta; /* cuenta es variable global */ main() { ... } y en el módulo auxil.c necesitamos utilizar la variable global cuenta declarada en princip.c, entonces tenemos la siguiente declaración: auxil.c extern int cuenta; func() { ... } 5.4.2 static Las variables estáticas, son variables permanentes, como las globales, pero su contenido es conocido sólo si se llama a la función donde fueron declaradas. Las variables estáticas pueden ser locales o globales. Ya se explicó las variables estáticas locales. Sobre las variables estáticas globales, podemos decir que solo pueden ser reconocidas y utilizadas únicamente en el archivo o módulo donde fueron declaradas. 5.4.3 register Las variables register, residen en uno o varios de los registros del CPU, no están en la memoria principal de la máquina. En una máquina con procesador de 16 bits (una PC,XT,AT, etc) una variable de clase register puede tener hasta 16 bits de longitud, es decir puede ser un char (8 bits), un int, unsigned int, etc. Las variables register pueden ser locales o parámetros formales, no pueden ser globales. Se caracterizan por ser sumamente

Page 39: Manual basico de_lenguje_c

35

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

veloces, auque son limitadas en su número y longitud. Un ejemplo de declaración es el siguiente: potencia(m,e); int m; register int e; 5.4.3 auto Las variables automáticas (auto) son las variables locales, y no es necesario la utilización de esta palabra clave por razones anteriormente expuestas en el estudio de variables locales. Se llaman automáticas porque se crean y se destruyen automáticamente al correr el bloque donde fueron declaradas. 5.5 INICIALIZACION DE VARIABLES La inicialización de variables permite que éstas tengan un valor al momento de compilación del programa. La inicialización de variables solo es posible para variables globales y estáticas. Observemos los siguiente ejemplos: char ch = 'a' ; int primero = '0' ; static float balance = 123.23 ; Mas adelante, en el estudio de tipos de datos derivados nos extenderemos en formas más complejas de inicialización. CAPITULO VI SENTENCIAS DE CONTROL C tiene una serie de sentencias de control. Para control de bucles o lazos: while, for, do-while. Sentencias condicionales: if y switch. Funciones que afectan al control de flujo: break, continue y goto. 6.1 VALORES true y false Las pruebas condicionales se basan en expresiones que sean verdaderas o falsas, en C un valor falso es un valor 0, y un verdadero es un valor diferente de 0. Por ejemplo si a==b, es falso, es decir, a es diferente de b, entonces el resultado de

Page 40: Manual basico de_lenguje_c

36

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

esta expresión será 0 (flase), caso contrario será un valor diferente de 0, para este caso es 1 (true). 6.2 LA SENTENCIA while La sentencia while ejecuta las sentencias dentro de un bloque mientras sea verdad una condición y tiene el siguiente formato: while (condición) { sentencias } ; Como vemos, antes de que se ejecuten las sentencias dentro del bloque, debe confirmarse la condición. Esta condición es una expresión booleana cuyo resultado será true o false. Veamos el siguiente ejemplo donde se imprimen los cuadrados del 1 al 10: int a; a = 1; while (a<=10) { printf(" %2d %3d \n" , a , a*a ); a++; } En caso de que al inicio del bucle while, el valor de a no fuera 1 sino 11, el bloque correspondiente al bucle no se hubiera ejecutado ni una sola vez. 6.3 LA SENTENCIA do-while En el bucle while primero se confirma un condición antes de proceder con la ejecución de sentencias, en do-while ocurre que primero se ejecuta sentencias y luego se verifica condición, esto nos dice que sentencias al menos se ejecutará una vez, el formato es el siguiente: do

Page 41: Manual basico de_lenguje_c

37

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

{ sentencias } while(condición) ; La salida del siguiente ejemplo: int a; a = 11; do { printf(" %2d %3d \n" , a , a*a ); a++; } while (a<=10) ; será: 11 121 por cuanto aunque no cumpla con la condición, al menos va a ejecutarse un vez. Si en lugar de la asignación a = 11; tendría-mos la asignación a=1; el ejemplo planteado es equivalente al ejemplo dado en while. 6.4 LA SENTENCIA for El formato de la sentencia for es el siguiente: for(inicialización ; condición ; incremento ) { sentencias } ; Donde sentencias se ejecuta un número de veces determinado por los argumentos de for. La inicialización es por lo general una sentencia de asignación para la variable de control, condición es la expresión booleana de terminación, incremento es la forma como se incrementa la variable inicializada. Para nuestro ejemplo: int a; for (a=1 ; a<=10 ; a++) { printf(" %2d %3d \n",a,a*a) ;

Page 42: Manual basico de_lenguje_c

38

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

} La variable de control es a. Un bucle infinito (sin salida), utilizando for sería: for (;;) printf("bucle infinito\b"); En la sentencia for, podemos utilizar el operador coma para más de una variables de control. Por ejemplo en el siguiente ejemplo se copia la cadena s en r, pero en reversa: reverse(s,r) char *s, *r ; { int i,j ; for ( i=strlen(s)-1,j=0 ; i>0 ; j++,i-- ) { r[i] = s[j]; } r[j] = '\0'; } Aquí podemos ver que existen dos variables de control, i y j, i va disminuyendo de valor, y j va aumentando. Se ejecutará la única sentencia, r[i] = s[j], mientras i sea mayor que 0. Un bucle (while, do-while, for) no necesariamente tiene cuerpo, por ejemplo, un bucle de retardo: for( i=0 ; i<1000 ; i++ ) ; no tiene ninguna sentencia de ejecución, lo único que hace es aumentar la variable de control, lo que produce un retardo. 6.5 LA SENTENCIA if-else La sentencia if ejecuta las sentencias1 en caso de que la condi-ción de un valor true o verdadero, caso contrario (else) ejecutará sentencias2. El formato es:

Page 43: Manual basico de_lenguje_c

39

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

if (condición) { sentencias1; } else { sentencias2; } Para el caso de sentencias de condición anidadas, else siempre corresponde al último if: if (condición1) if (condición2) { sentencias1 ; } else { sentencias2 ; } el último else corresponde al if de condición2. 6.6 LA SENTENCIA switch En if, condición podía tener solo dos valores true o flase, sin embargo, son muchos los casos en que una condición adquiere n valores (valor1, valor2, etc), debiendo tener sentencias diferen-tes para cada caso, veamos el formato: switch (condición); { case valor1: sentencias1; break; case valor2: sentencias2; break;

Page 44: Manual basico de_lenguje_c

40

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

... case valorn sentenciasn; break; default: sentenciasd } Default ejecutará un conjunto de sentencias cuando han fallado todos los valores posibles. Si la condición es uno de los valores propuestos (valor1, valor2,... ,valorn), se ejecutarán las sentencias respectivas hasta encontrar un break. La sentencia switch sólo puede comprobar la igualdad, en cambio que if puede evaluar expresiones relacionales y lógicas. 6.7 LA SENTENCIA break La sentencia break tiene dos usos: 1) finaliza un case dentro de un switch (como ya lo vimos en el

estudio de la sentencia switch). 2) forzamos la salida de cualquiera de los bucles estudiados

(while, do while, for), dejando de lado las condiciones de repetición y el resto de sentencias que se encuentren luego del break en el bloque de repetición.

6.8 LA SENTENCIA continue Si break forza la terminación de un bucle, continue obliga a que se vuelva a evaluar la condición del bucle para que pueda volverse a ejecutar el bloque de repetición, esto, dejando de lado las sentencias que sigan a continuación de continue; en el siguiente ejemplo, se obliga a leer un dígito o un caracter: char ch; for (;;); { ch = getchar();

Page 45: Manual basico de_lenguje_c

41

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

if (ch>32 && ch<127) break else { if ( ch<=32 ) continue else printf("ascii extendido"); } } 6.9 LA SENTENCIA exit() La función exit() obliga a la terminación de un programa. Puede tener como argumento a 0, exit(0), que significa terminación normal, en caso de que tenga como argumento a un número diferente de 0, se supone que puede acceder a analizar el error con ese argumento. 6.10 LA SENTENCIA goto El formato de goto es: goto <etiqueta> ; y el de etiqueta es: <nombre-etiqueta>: La sentencia goto nos permite dar un salto a la parte del programa donde se encuentre la etiqueta respectiva. Un programa debidamente estructurado debe evitar la utilización del goto, de hecho es la "sentencia prohibida" en la programación estructurada.

Page 46: Manual basico de_lenguje_c

42

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

CAPITULO VII INTRODUCCION A LA PROGRAMACION

ORIENTADA A OBJETOS "Si no se conoce con exactitud qué es lo que un programa

contemplará, es mejor es no comenzar a escribirlo" Tenemos una empresa que es a la vez un conglomerado de varias empresas. El software debe reconocer las demandas existentes de dicha empresa así como la evolución a nuevas necesidades, razón suficiente como para utilizar las técnicas orientadas a objeto en la programación. En un primer acercamiento, se han establecido los siguientes objetivos: * Un sistema de control de inventario. * Un sistema de ventas. * Una base de datos del personal. * Una consolidación de los datos relevantes de las tres

partes anteriores. Un primer problema que se encuentra, la incertidumbre al no quedar claramente expuestas las necesidades de la empresa. Esta situación cambiará con el tiempo. Un proceso continuo de especificaciones, implementación y refinamiento de las especificaciones es el método que siguen las técnicas orientadas a objeto. Una de las ventajas de estas técnicas, es que el tiempo que el programador utiliza para reescribir código, ahora se lo utilizará en mejorar las aplicaciones. Lo primero que debemos hacer, es descomponer los estados requeri-dos como existen en la actualidad: El sistema de inventario requerirá de ítemes. El sistema de ventas requerirá de vendedores y distribuidores que harán constar las ordenes. La base de datos del personal implicará la existencia de gente que trabaje para la empresa.

Page 47: Manual basico de_lenguje_c

43

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

Por hoy vamos a ignorar -no olvidar- la consolidación, que es la interrelación de todos los aspectos anteriores. Los sistemas orientados a objeto tratan con objetos que son el análogo de las cosas del mundo real. Los objetos son autocon-tenidos, resultan de datos y métodos para manipular esos datos: objetos([datos],[métodos]) El mayor concepto que está atado a la programación orientada a objeto es el modelamiento, es decir que el trabajo del programador es construir modelos de software de las cosas del mundo real. Si ese trabajo se lo realiza en forma correcta, muchos de los problemas encontrados en la interacción de esos objetos, dejarán de ser problema, lo que nos llevará a una situación diferente que no se la puede encontrar en los lenguajes tradicionales. En el diseño orientado a objeto, si el primer nivel de las operaciones específicas del objeto están correctamente concebidas, entonces el segundo nivel será relativamente fácil de implementar. Esto ocurre porque las operaciones de la aplicación global son construidas desde operaciones basadas en subcomponentes específicos de la aplicación. Se facilitan las cosas si se explotan las bondades de bajo nivel, y si no se logra hacerlo, entonces es mejor reimplementarlas. Nos resultan familiares las librerías de los compiladores C, las mismas que nos ofrecen operaciones de bajo nivel con las que construimos funciones primitivas. Estas funciones para ser utilizadas, así como las operaciones de bajo nivel de las libre-rías, deben estar bien implementadas y documentadas. Retornando a la empresa, tomaremos las tres secciones planteadas las que serán descompuestas. Para hacerlo debemos hacer una cuidadosa examinación de las interrelaciones entre ellas. Primero, el control de inventario es básicamente un contenedor de ítemes de inventario. Cada ítem es un objeto con algún dato asociado aún desconocido. Pero podemos asumir algunas cosas previas: * Existen cierto número de ítemes en stock para cada ítem. * Cada ítem tiene un número de inventario o número parte.

Page 48: Manual basico de_lenguje_c

44

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

* Cada ítem es comprado a uno o mas distribuidores. * Hay una historia de compras y ventas para cada ítem. Segundo, el control de ventas es un contenedor de ventas indivi-duales. Para cada venta debe haber: * Una orden del cliente. * Información acerca de la entrega final. * Información acerca del pago. Y, tercero, la base de datos de los empleados, tiene una colección de empleados individuales, que contendrá como mínimo: * Dirección del empleado. * Información del impuesto. * Historial del empleo y descripción del trabajo. Lo primero que debemos observar son las similitudes entre cada objeto para que sean explotadas. Para este caso, por ejemplo, el sistema de inventario conoce de distribuidores, el sistema de ventas conoce de clientes y el sistema de empleados conoce de empleados. Cada uno de esos objetos (clientes, distribuidor y empleados) son personas, con nombre y dirección. Por lo tanto, debe haber un tipo de objeto general en el sistema, un objeto que define la característica general de cada uno de esos elementos, las características que todos ellos tienen en común. Podemos decir que esos elementos son clases de otro objeto más general, al que llamaremos entidad. En la POO cada objeto está definido como una clase que pueda ser vista como un padrón para la creación de objetos específicos que tengan un comportamiento similar. Las clases son agrupadas en jerarquías, que contemplarán clases muy generales, hasta aquellas que aplicarán las características a clases específicas. Por ejemplo, tenemos la clase "carnívoro", que tiene las características específicas para todos los animales carnívoros, es decir trata por igual a perros y leones, porque la característica común de los carnívoros es que comen carne. A un

Page 49: Manual basico de_lenguje_c

45

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

nivel más bajo, entonces ya sabremos que los perros son muy diferentes de los leones, entonces para describir estas clases, ya no será necesario repetir las características de los carnívoros, solo será necesario describir las características específicas. En este punto ya nos vamos aproximando a una estructura de la Compañía de Comercio, la que por lo menos contiene tres coleccio-nes distintas de objetos, una para inventario, otra para ventas y otra para personal. Estas colecciones actúan de la misma manera, es decir que debemos manipular una lista de sus respectivos tipos, y dando un significado uniforme para acceder a ellos. Cada uno de esos subtipos tienen una organización única para un propósito individual, sin embargo, todos utilizan la clase entidad para mantener información acerca de las varias clases de gente con las que se debe tratar. Esto permite que asumamos dos cosas importantes acerca de las operaciones del sistema. Los tres grupos de información son colecciones de datos que operan de la misma manera. No importa que sea un ítem de inventario, un registro de vendedor, o un registro de empleado, serán recuperados de una colección, el mecanismo para recuperación es el mismo. Al nivel mas alto, la aplicación puede ser esperada para saber que esas son colecciones y para saber como acceder a sus contenidos. Segundo, hay una clase objeto, Entidad, que agrupa a personas tales como vendedo-res, empleados y distribuidores. Esta clase define cosas genera-les para todas las personas, desde compañías hasta personas reales. Por lo tanto deberían contener cosas como: * El nombre de la persona o compañía. * La dirección de la persona o compañía. Debemos tener presente que un objeto Entidad no determina si es una real o una compañía. Ello ocurrirá cuando tengamos clases más detalladas de entidades para hacer esta distinción. La programación orientada a objeto nos permite el desarrollo de software en forma de top-down sin los temores irritantes sobre la integración final de los módulos que acompañan a este método en la programación tradicional. Parece que vamos necesitar un objeto general llamado Colección, que debe comportarse de una manera uniforme. Todos los accesos a las bases de datos especializadas se realizará a través de esa colección, y todos los accesos son garantizados que se harán de la misma manera. Ahora es cuando

Page 50: Manual basico de_lenguje_c

46

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

podemos ignorar al nivel superior y comenzar una descomposición más detallada de cada elemento de la base de datos. Previo a la resolución de los problemas de la compañía, deben ser direccionados algunos problemas tácticos del programador. Real-mente no hay problemas, pero hay límites dentro de los que el programador debe operar, y en los que debe definir con exactitud la responsabilidad de hacer en ese momento. La primera área es la información que debe manejar y la que no debería manejar. La segunda es que funcionalidad el programador puede asumir en este instante y cual puede ser postergada para otro momento. Generalización vs. especialización Antes de empezar a diseñar los componentes de la base de datos especializada, las responsabilidades del programador deben ser claramente delineadas. Por ejemplo, para el ítem de inventario, debe haber un número de parte y una descripción. No todos tienen color y talla. La POO nos permite definir lo que es común para todos los objetos y que es particular para unos pocos. La POO permite al diseñador posponer la especialización hasta que la estructura general ha sido construida. Una regla general se vuelve vital en la POO: Ignorar casos especiales hasta que no puedan ser ignorados mas. Algunos programadores comienzan buscando las peculiaridades de la información, ha tal punto que llegan a tener información que no puede ser relacionada, en lugar de tener una colección de infor-mación coherente sin excepciones y con rasgos comunes. La especialización es el último paso a ser desarrollado, luego de tener todas las similitudes del sistema a ser explotado. Después de que el diseño del sistema general ha sido llevado a cavo y luego de que las excepciones han sido conocidas entonces e imple-mentadas, continúa un proceso de búsqueda de excepciones raras hasta que el cliente encuentra sus propios errores. Debemos generalizar bien para que podamos mejorar y aumentar la especia-lización al sistema sin afectar cualquier trabajo desarrollado previamente. Funcionalidad Pospuesta. En la programación tradicional, primero creamos las estructuras de datos, y luego creamos las funciones para manipular dichas

Page 51: Manual basico de_lenguje_c

47

───────────────────────────────────────────────────────────────── Manual del Lenguaje C Laboratorio de Sistemas - EPN

estructuras de datos. En POO, esto no ocurre. Cuando se crea una nueva estructura u objeto se marca el fin de la responsabilidad corriente del programador