lenguaje en c

40
Introducción a la programación en lenguaje C

Upload: daniel-bg

Post on 24-Jun-2015

429 views

Category:

Documents


2 download

DESCRIPTION

Aprende a programar en "C"

TRANSCRIPT

Page 1: LENGUAJE en C

Introducción a la programación en

lenguaje C

Page 2: LENGUAJE en C

Introducción

C es un lenguaje de programación de propósito general que ofrece economía sintáctica, control de flujo y estructuras sencillas y un buen conjunto de operadores. No es un lenguaje de muy alto nivel y más bien un lenguaje pequeño, sencillo y no está especializado en ningún tipo de aplicación. Esto lo hace un lenguaje potente, con un campo de aplicación ilimitado y sobre todo, se aprende rápidamente. En poco tiempo, un programador puede utilizar la totalidad del lenguaje.

Este lenguaje ha sido estrechamente ligado al sistema operativo UNIX, puesto que fueron desarrollados conjuntamente. Sin embargo, este lenguaje no está ligado a ningún sistema operativo ni a ninguna máquina concreta. Se le suele llamar lenguaje de programación de sistemas debido a su utilidad para escribir compiladores y sistemas operativos, aunque de igual forma se pueden desarrollar cualquier tipo de aplicación.

La base del C proviene del BCPL, escrito por Martin Richards, y del B escrito por Ken Thompson en 1970 para el primer sistema UNIX en un DEC PDP-7. Estos son lenguajes sin tipos, al contrario que el C que proporciona varios tipos de datos. Los tipos son caracteres, números enteros y en coma flotante, de varios tamaños. Además se pueden crear tipos derivados mediante la utilización de punteros, vectores, registros y uniones. El primer compilador de C fue escrito por Dennis Ritchie para un DEC PDP-11 y escribió el propio sistema operativo en C.

Page 3: LENGUAJE en C

C trabaja con tipos de datos que son directamente tratables por el hardware de la mayoría de computadoras actuales, como son los caracteres, números y direcciones. Estos tipos de datos pueden ser manipulados por las operaciones aritméticas que proporcionan las computadoras. No proporciona mecanismos para tratar tipos de datos que no sean los básicos, debiendo ser el programador el que los desarrolle. Esto permite que el código generado sea muy eficiente y de ahí el éxito que ha tenido como lenguaje de desarrollo de sistemas. No proporciona otros mecanismos de almacenamiento de datos que no sea el estático y no proporciona mecanismos de entrada ni salida. Ello permite que el lenguaje sea reducido y los compiladores de fácil implementación en distintos sistemas. Por contra, estas carencias se compensan mediante la inclusión de funciones de librería para realizar todas estas tareas, que normalmente dependen del sistema operativo.

Originariamente, el manual de referencia del lenguaje para el gran público fue el libro [1] de Kernighan y Ritchie, escrito en 1977. Es un libro que explica y justifica totalmente el desarrollo de aplicaciones en C, aunque en él se utilizaban construcciones, en la definición de funciones, que podían provocar confusión y errores de programación que no eran detectados por el compilador. Como los tiempos cambian y las necesidades también, en 1983 ANSI establece el comité X3J11 para que desarrolle una definición moderna y comprensible del C. El estándar está basado en el manual de referencia original de 1972 y se desarrolla con el mismo espíritu de sus creadores originales. La primera versión de estándar se publicó en 1988 y actualmente todos los compiladores utilizan la nueva definición. Una aportación muy importante de ANSI consiste en la definición de un conjunto de librerías que acompañan al compilador y de las funciones contenidas en ellas. Muchas de las operaciones comunes con el sistema operativo se realizan a través de estas funciones. Una colección de ficheros de encabezamiento, headers, en los que se definen los tipos de datos y funciones incluidas en cada librería.

Page 4: LENGUAJE en C

Los programas que utilizan estas bibliotecas para interactuar con el sistema operativo obtendrán un comportamiento equivalente en otro sistema.

Programas

La mejor forma de aprender un lenguaje es programando con él. El programa más sencillo que se puede escribir en C es el siguiente:

main()

{

}

Como nos podemos imaginar, este programa no hace nada, pero contiene la parte más importante de cualquier programa C y además, es el más pequeño que se puede escribir y que se compile correctamente. En el se define la función main, que es la que ejecuta el sistema operativo al llamar a un programa C. El nombre de una función C siempre va seguida de paréntesis, tanto si tiene argumentos como si no. La definición de la función está formada por un bloque de sentencias, que esta encerrado entre llaves {}.

Page 5: LENGUAJE en C

Forma general de un programa en C

declaraciones globales

main ()

{

Variables locales

secuencia de sentencias

}

f1 ()

{

Variables locales

Secuencia de sentencias

}

.

fn ()

{

Variables locales

Secuencia de sentencias

}

Page 6: LENGUAJE en C

Un programa algo más complicado pero que hace algo, es el siguiente:

#include <stdio.h>

main()

{

printf("Hola amigos!\n");

}

Con el visualizamos el mensaje Hola amigos! en el terminal. En la primera línea indica que se tengan en cuenta las funciones y tipos definidos en la librería stdio (standard input/output). Estas definiciones se encuentran en el fichero header stdio.h. Ahora, en la función main se incluye una única sentencia que llama a la función printf. Esta toma como argumento una cadena de caracteres, que se imprimen van encerradas entre dobles comillas " ". El símbolo \n indica un cambio de línea. Hay un grupo de símbolos, que son tratados como caracteres individuales, que especifican algunos caracteres especiales del código ASCII. Los más importantes son:

Page 7: LENGUAJE en C

\a alert

\b backspace

\f formfeed

\n newline

\r carriage return

\t horizontal tab

\v vertical tab

\\ backslash

\‘ single quote

\“ double quote

\OOO visualiza un carácter cuyo código ASCII es OOO en octal.

\xHHH visualiza un carácter cuyo código ASCII es HHH en hexadecimal.

Page 8: LENGUAJE en C

El desarrollo de un programa

Un programa C puede estar formado por diferentes módulos o fuentes. Es conveniente mantener los fuentes de un tamaño no muy grande, para que la compilación sea rápida. También, al dividirse un programa en partes, puede facilitar la legibilidad del programa y su estructuración. Los diferentes fuentes son compilados de forma separada, únicamente los fuentes que han sido modificados desde la última compilación, y después combinados con las librerías necesarias para formar el programa en su versión ejecutable.

Los comandos necesarios para compilar, linkar y ejecutar un programa dependen del sistema operativo y debemos dirigirnos a los manuales correspondientes para conocer la sintaxis exacta. Como forma más común podemos dar la siguiente:

cc prog

cc modulo1, modulo2

link prog, modulo1, modulo2

prog

Page 9: LENGUAJE en C

Un mapa conceptual de la memoria para un programa en C

Pila

Montón

Variables Globales

Código de programa

Un programa compilado en C crea y usa cuatro regiones de memoria lógicas diferentes que sirven para funciones específicas. La primera región es la memoria que contiene realmente el código del programa. La siguiente región es la memoria donde se guardan las variables globales. Las dos regiones restantes son la pila ( en inglés, STACK ) y el montón ( en inglés, HEAP ). La pila se usa para muchas cosas durante la ejecución del programa. Mantiene las direcciones de vuelta para las llamadas a funciones, así como las variables locales. También sirve para salvar el estado de la CPU. El montón es la región de memoria libre que puede usar el programa mediante las funciones de asignación dinámicas para cosas las listas enlazadas y los árboles.

Page 10: LENGUAJE en C

Proceso de compilación

Page 11: LENGUAJE en C

Los términos que siguen se usarán frecuentemente a lo largo de este material :

Código Fuente : El texto de un programa que un usuario puede leer; normalmente considerado como el programa. El código fuente es la entrada al compilador de C.

Código Objeto : La traducción del código fuente de un programa a código de máquina, que es el que el computador puede leer y ejecutar directamente. El código objeto es la entrada al enlazador.

Enlazador : Un programa que enlaza funciones compiladas por separado para producir un solo programa. Combina las funciones de la biblioteca estándar de C con el código que se ha escrito. La salida del enlazador es un programa ejecutable.

Biblioteca : El archivo que contiene las funciones estándar que se pueden usar en los programas. Las funciones incluyen todas las operaciones de E/S, así como otras rutinas útiles.

Tiempo de Compilación : Lo que sucede mientras un programa es compilado. Algo que ocurre con frecuencia durante el tiempo de compilación es un error de sintaxis.

Tiempo de ejecución : Lo que sucede mientras un programa es ejecutado.

Page 12: LENGUAJE en C

Nombres de identificadores

Los nombres usados para referirse a las variables, las funciones, las etiquetas y otros objetos definidos por el usuario se conocen como Identificadores. La longitud de un identificador en C puede variar entre uno y treinta dos caracteres. El primer carácter debe ser una letra o un símbolo de subrayado ( guión bajo “_ “ ) y los caracteres siguientes pueden ser letras, números o símbolos de subrayados. El lenguaje C también permite usar el símbolo $ en un nombre de identificador, pero no se trata de algo estándar, siendo recomendable no hacerlo. A continuación se muestran algunos nombres de identificadores correctos e incorrectos.

Correctos Incorrectos

cont 1cont

prueba23 Hola!

balance_total balance..total

En C las minúsculas y las mayúsculas se tratan como distintas. Así, cuenta, Cuenta y CUENTA son tres identificadores distintos. Un identificador no puede ser igual que una palabra clave del lenguaje y no debe tener el mismo nombre que alguna función ya escrita o que se encuentre en la biblioteca del lenguaje.

Page 13: LENGUAJE en C

Tipos básicos y variables

Los tipos de datos básicos definidos por C son caracteres, números enteros y números en coma flotante. Los caracteres son representados por char, los enteros por short, int, long y los números en coma flotante por float y double. Los tipos básicos disponibles y su tamaño son:

char Carácter (normalmente 8 bits)

short Entero corto con signo (normalmente 16 bits)

int Entero con signo (depende de la implementación)

unsigned Entero sin signo (depende de la implementación)

long Entero largo con signo (normalmente 32 bits)

float Flotante simple (normalmente 32 bits)

double Flotante doble (normalmente 64 bits)

La palabra unsigned en realidad es un modificador aplicable a tipos enteros, aunque si no se especifica un tipo se supone int. Un modificador es una palabra clave de C que indica que una variable, o función, no se comporta de la forma normal. Hay también un modificador signed, pero como los tipos son por defecto con signo, casi no se utiliza.

Page 14: LENGUAJE en C

Tamaños y rangos de los tipos de datos básicos

Tipo Tamaño en Bits Rango

char 8 0 a 255

int 16 -32.768 a 32.767

float 32 3,4E-38 a 3,4E +38

double 64 1,7E –308 a 1,7E+308

void 0 sin valor

Los valores del tipo char se usan normalmente para guardar valores definidos el juego de caracteres ASCII, así como cualquier cantidad de 8 bits. Las variables de int se usan para guardar cantidades enteras. Las variables de tipo float o double se usan para guardar números reales.

El tipo void tiene tres usos.

- declarar explícitamente una función como que no devuelve valor alguno.

- declarar explícitamente una función sin parámetros.

- para crear punteros genéricos.

Page 15: LENGUAJE en C

Modificadores de tipos

A excepción del tipo void, los tipos de datos básicos pueden tener distintos modificadores precediéndolos. Un modificador se usa para alterar el significado del tipo base para que se ajuste más precisamente a las necesidades de cada momento. A continuación se muestra la lista de modificares :

signed

unsigned

long

short

Los modificadores signed, unsigned, short y long se pueden aplicar a los tipos base entero y de carácter. Sin embargo, long también se puede aplicar a double. El uso de signed en enteros es redundante ( pero admisible ).

La diferencia entre enteros con y sin signo está en cómo se interpreta el bit más significativo del entero. Si se especifica un entero con signo, el compilador genera código que asume que el bit más significativo va ser usado como un indicador de signo. Si el indicador de signo es 0, entonces el número es positivo; si es un 1, el número es negativo. Por ejemplo

127 en binario es 00000000 01111111

-127 en binario es 10000000 01111111

Page 16: LENGUAJE en C

Todas las combinaciones de los tipos básicos y los modificadores en C

Tipo Tamaño en Bits Rango

char 8 -128 a 127

unsigned char 8 0 a 255

signed char 8 -128 a 127

int 16 -32.768 a 32.767

unsigned int 16 0 a 65535

signed int 16 -32.768 a 32.767

short int 16 -32.768 a 32.767

unsigned short int 16 0 a 65535

signed short int 16 -32.768 a 32.767

long int 32 -2147483648 a 2147483648

signed long int 32 -2147483648 a 2147483648

float 32 3,4E-38 a 3,4E+38

double 64 1,7E-308 a 1,7E+308

long double 64 1,7E-308 a 1,7E+308

Page 17: LENGUAJE en C

Declaración de variables

Todas las variables han de ser declaradas antes de poder ser usadas. La forma general de declaración es la que se muestra a continuación :

tipo lista_de_variables;

Aquí, tipo debe ser un tipo válido de C y la lista_de_variables puede consistir en uno o más nombres de identificadores separados por comas. A continuación se muestran algunas declaraciones :

int i, j, l ;

short int si ;

unsigned int ui ;

double balance, beneficio, pérdida ;

Hay que tener claro que en C el nombre de una variable no tiene nada que ver con su tipo.

Existen tres sitios básicos donde se pueden declarar variables: dentro de las funciones, en la definición de parámetros de funciones y fuera de todas las funciones.

Estas variables son, respectivamente, las variables locales, los parámetros formales y las variables globales.

Page 18: LENGUAJE en C

Variables Locales

Las variables que se declaran dentro de una función se denominan variables locales. En algunos libros de C, estas variables se denominan automáticas, debido a que en C se pueden usar la palabra clave ( opcional ) auto para declararlas. Dado que el término variable local es el más común, es lo que usaremos para su identificación. Las variables locales pueden ser denominadas sólo por sentencias que estén dentro del bloque en el que han sido declaradas. O dicho de otra forma, las variables locales no son conocidas fuera de su propio bloque de código. Recordar que un bloque de código comienza con una llave abierta y termina con una llave cerrada.

Una de las cosas más importantes que hay que comprender sobre las variables locales es que solo existen mientras se está ejecutando el bloque de código en el que son declaradas. O sea, la variable local se crea al entrar en el bloque y se destruye al salir de él.

El bloque de código más normal en el que se declaran variables locales es la función. Por ejemplo :

void func1 ( void ) void func2 ( void)

{ {

int x ; int x ;

x = 10 ; x = -199 ;

} }

Page 19: LENGUAJE en C

La variable entera x se declara dos veces, una vez en func1() y otra en func2(). La x de func1() no corresponde ni tiene relación con la x de func2(). La razón es que cada x sólo es conocida en el propio código en que se ha declarado la variable.

La mayoría de los programadores declaran todas las variables que se necesitan en una función al principio del bloque de código de la misma. Esto se hace así para que sea más fácil al leer el código saber qué variables se usan. Sin embargo, no es necesario hacerlo así, ya que se pueden declarar variables locales en cualquier bloque de código. Para comprender cómo funciona esto, considere la siguiente función :

Void f( void)

{

int t ;

scanf( “%d”, &t );

if ( t== 1 ) {

char s[80]; /* esta se crea sólo al entrar en este bloque */

printf(“introduzca el nombre : “ );

gets(s);

procesar (s) ;

}

/* aquí no se conoce a s */

}

Page 20: LENGUAJE en C

Aquí, la variable local s se crea tras entrar en el bloque de código if y se destruye tras salir de él. Más aún s sólo es conocida dentro del bloque if y no puede ser denominada en ninguna parte fuera de él.

Dado que las variables locales se crean y se destruyen cada vez que se entra o se sale de la función en la que son declaradas, no pueden retener sus valores entre llamadas. ( Sin embargo, es posible indicar al compilador que retenga sus valores mediante el uso del modificador static ).

Parámetros formales

Si una función va a usar argumentos, debe declarar las variables que van a aceptar los valores de los argumentos. Estas variables son los parámetros formales de la función.

Se comportan como cualquier otra variable local de la función. Como se muestra en el siguiente fragmento de programa, sus declaraciones se dan tras el nombre de la función y entre paréntesis.

/* Devuelve 1 si c es parte de la cadena s; sino 0 */

Esta_en( char *s, char c)

{

while (*s)

if (*s == c ) return 1 ;

else s++ ;

return 0 ;

}

Page 21: LENGUAJE en C

La función esta_en() tiene dos argumentos s y c. Se debe indicar al compilador de C qué tipo de variables son los parámetros formales, haciéndolo tal como se ha mostrado. Una vez que se ha hecho, pueden ser usadas dentro de la función como variables locales normales. Al igual que las variables locales, también son dinámicas y se destruyen al salir de la función.

Hay que asegurar que los parámetros formales que se declaran sean del mismo tipo que los argumentos que se usan en la llamada a la función. Si existe una diferencia de tipo, se pueden dar unos resultados inesperados. A diferencia de otros lenguajes, C es muy robusto y normalmente siempre hace algo, incluso aunque no sea lo que se desea. Hay muy pocos errores en tiempo de ejecución y no se comprueban los límites. Como programador, hay que asegurar de que no se den errores de inconsistencia de tipos.

Al igual que con las variables locales, se pueden hacer asignaciones a los parámetros formales de una función o usarlos en cualquier expresión válida en C. Aunque esas variables reciben sus valores de los argumentos pasados a la función, se pueden usar como cualquier otra variable local.

Variables Globales

A diferencia de las variables locales, las variables globales se conocen a lo largo de todo el programa y se pueden usar en cualquier parte del código. Además, mantienen su valor durante toda la ejecución del programa. Las variables globales se crean al declararlas en cualquier parte fuera de una función. Pueden ser accedidas por cualquier expresión independientemente de la función en la que se encuentre la expresión.

En el programa que sigue se puede ver que la variable cuenta ha sido declarada fuera de todas las funciones. Aunque se declaración aparece antes de la función main(), se podría haber colocado en cualquier lugar anterior a su primer uso, mientras no sea en una función. Sin embargo, lo mejor es declarar todas las variables globales al principio del programa.

Page 22: LENGUAJE en C

# include <stdio.h>

void func1 ( void), func2(void);

int cuenta; /* cuenta es global */

main ( void )

{

cuenta = 100 ;

func1() ;

return 0; /* comunicar el éxito al programa */

}

void func1 ( void ) void func2 ( void )

{ {

int temp; int cuenta;

temp = cuenta ; for ( cuenta = 1; cuenta <10; cuenta++)

func2() ; putchar(‘_’) ;

printf( “cuentas es %d”, cuenta ); }

}

Page 23: LENGUAJE en C

Observando detenidamente este programa, debe estar claro que aunque ni main() ni func1() han declarado la variable cuenta, ambas pueden usarla. Sin embargo, la func2() declara una variable local llamada cuenta. Cuando func2() hace referencia a cuenta, sólo hace referencia a su variable local, no a la global. Si una variable global y una variable local tienen el mismo nombre, todas las referencias a ese nombre de variable dentro de la función donde se ha declarado la variable local se refieren a esa variable local y no tienen efecto sobre la variable global. Esto es algo conveniente. Sin embargo, si se olvida, el programa puede actuar de forma extraña, incluso aunque “ parezca “ correcto.

El almacenamiento de las variables globales se hace en una región de memoria fija establecida para este propósito por el compilador. Las variables globales son muy útiles cuando se usan los mismos datos en varias funciones del programa. Sin embargo, se debe evitar el uso de variables globales innecesarias, por tres razones :

1.- Utilizan memoria todo el tiempo de ejecución del programa, no solo cuando se necesitan.

2.- El uso de una variable global cuando se podría usar una variable local hace que la función sea menos general debido a que depende de algo que debe estar definido fuera de ella.

3.- El uso de un gran número de variables globales puede producir errores en el programa debido a efectos secundarios desconocidos y no deseables.

Page 24: LENGUAJE en C

Por ejemplo, a continuación se muestran dos formas de escribir mul () – una sencilla función que calcula el producto de dos enteros .

General Espeficica

mul ( inte x, int y ) int x, y ;

{ mul ( void )

return ( x * y ) {

} return ( x * Y )

}

Ambas funciones devuelven el producto de las variables x e y. Sin embargo, la versión generalizada, o parametrizada, se puede usar para devolver el producto de cualesquiera dos enteros, mientras que la versión específica sólo se puede usar para calcular el producto de las variables globales x e y.

Page 25: LENGUAJE en C

Las variables son definidas utilizando un identificador de tipo seguido del nombre de la variable. Veamos el siguiente programa.

#include <stdio.h>

main()

{

float cels, farh;

farh = 35.0;

cels = 5.0 * ( farh - 32.0 ) / 9.0;

printf(">>> %f F son %f C\n", farh, cels );

}

En el programa anterior se definen dos variables float, se asigna un valor a la primera y se calcula la segunda mediante una expresión aritmética. Las asignaciones en C también son una expresión, por lo que se pueden utilizar como parte de otra expresión, pero según que prácticas de este tipo no son muy recomendables ya que reducen la legibilidad del programa. En la instrucción printf, el símbolo %f indica que se imprime un número en coma flotante.

Page 26: LENGUAJE en C

Hay un tipo muy importante que se representa por void que puede significar dos cosas distintas, según su utilización. Puede significar nada, o sea que si una función devuelve un valor de tipo void no devuelve ningún resultado, o puede significar cualquier cosa, como puede ser un puntero a void es un puntero genérico a cualquier tipo de dato. Más adelante veremos su utilización.

Funciones

Un programa C está formado por un conjunto de funciones que al menos contiene la función main. Una función se declara con el nombre de la función precedido del tipo de valor que retorna y una lista de argumentos encerrados entre paréntesis. El cuerpo de la función está formado por un conjunto de declaraciones y de sentencias comprendidas entre llaves. Veamos un ejemplo de utilización de funciones:

Page 27: LENGUAJE en C

#include <stdio.h>

#define VALOR 5

#define FACT 120

int fact_i ( int v )

{

int r = 1, i = 0;

while ( i <= v ) {

r = r * i;

i = i + 1;

}

return r;

}

int fact_r ( int v )

{

if ( v == 0 )

return 1;

else

return v * fact_r(v-1);

}

Page 28: LENGUAJE en C

main()

{

int r, valor = VALOR;

if ( (r = fact_i(valor)) != fact_r(valor) )

printf("Codificación errónea!!.\n");

else

if ( r == FACT )

printf("Codificación correcta.\n");

else

printf("Algo falla!!.\n");

}

Page 29: LENGUAJE en C

Se definen dos funciones, fact_i y fact_r, además de la función main. Ambas toman como parámetro un valor entero y devuelven otro entero. La primera calcula el factorial de un número de forma iterativa, mientras que la segunda hace lo mismo de forma recursiva.

Todas las líneas que comienzan con el símbolo # indican una directiva del precompilador. Antes de realizar la compilación en C se llama a un precompilador cuya misión es procesar el texto y realizar ciertas sustituciones textuales. Hemos visto que la directiva #include incluye el texto contenido en un fichero en el fuente que estamos compilando. De forma parecida, #define nombre texto sustituye todas las apariciones de nombre por texto. Así, en el fuente, la palabra VALOR se sustituye por el número 5.

El valor que debe devolver una función se indica con la palabra return. La evaluación de la expresión debe dar una valor del mismo tipo de dato que el que se ha definido como resultado. La declaración de una variable puede incluir una inicialización en la misma declaración. Se debe tener muy en cuenta que en C todos los argumentos son pasados 'por valor'. No existe el concepto de paso de parámetros 'por variable' o 'por referencia'.

Veamos un ejemplo:

Page 30: LENGUAJE en C

int incr ( int v )

{

return v + 1;

}

main()

{

int a, b; b = 3;

a = incr(b);

/*

a = 4 mientras que

b = 3. No ha cambiado después de la llamada.

*/

}

En el ejemplo anterior el valor del parámetro de la función incr, aunque se modifique dentro de la función, no cambia el valor de la variable b de la función main. Todo el texto comprendido entre los caracteres /* y */ son comentarios al programa y son ignorados por el compilador. En un fuente C los comentarios no se pueden anidar.

Page 31: LENGUAJE en C

Expresiones y operadores

Los distintos operadores permiten formar expresiones tanto aritméticas como lógicas. Los operadores aritméticos y lógicos son:

+, - suma, resta

++, -- incremento, decremento

*, /, % multiplicación, división, módulo

>>, << rotación de bits a la derecha, izquierda.

& AND booleano

| OR booleano

^ EXOR booleano

~ complemento a 1

! complemento a 2, NOT lógico

==, != igualdad, desigualdad

&&, || AND, OR lógico

<, <= menor, menor o igual

>, >= mayor, mayor o igual

Page 32: LENGUAJE en C

En estos operadores deben tenerse en cuenta la precedencia de operadores y las reglas de asociatividad, que son las normales en la mayoría de lenguajes. Se debe consultar el manual de referencia para obtener una explicación de tallada. Además hay toda una serie de operadores aritméticos con asignación, como pueden ser += y ^=.

En la evaluación de expresiones lógicas, los compiladores normalmente utilizan técnicas de evaluación rápida. Para decidir si una expresión lógica es cierta o falsa muchas veces no es necesario evaluarla completamente. Por ejemplo una expresión formada <exp1> || <exp2>, el compilador evalúa primero <exp1> y si es cierta, no evalúa <exp2>. Por ello se deben evitar construcciones en las que se modifiquen valores de datos en la propia expresión, pues su comportamiento puede depender de la implementación del compilador o de la optimización utilizada en una compilación o en otra. Estos son errores que se pueden cometer fácilmente en C ya que una asignación es también una expresión.

Debemos evitar:

if (( x++ > 3 ) || ( x < y ))

y escribir en su lugar:

x++;

if (( x > 3 ) || ( x < y ))

Page 33: LENGUAJE en C

Hay un tipo especial de expresión en C que se denomina expresión condicional y está representada por los operadores ? : . Su utilización es como sigue: <e> ? <x> : <y>. Se evalúa si e entonces x; si no, y.

int mayor ( int a, int b )

{

return ( a > b ) ? TRUE : FALSE;

}

waste_time ()

{

float a, b = 0.0;

( b > 0.0 ) ? sin(M_PI / 8) : cos(M_PI / 4);

}

Page 34: LENGUAJE en C

Conversión de tipos

Cuando escribimos una expresión aritmética a+b, en la cual hay variables o valores de distintos tipos, el compilador realiza determinadas conversiones antes de que evalúe la expresión. Estas conversiones pueden ser para 'aumentar' o 'disminuir' la precisión del tipo al que se convierten los elementos de la expresión. Un ejemplo claro, es la comparación de una variable de tipo int con una variable de tipo double. En este caso, la de tipo int es convertida a double para poder realizar la comparación.

Los tipos pequeños son convertidos de la forma siguiente: un tipo char se convierte a int, con el modificador signed si los caracteres son con signo, o unsigned si los caracteres son sin signo. Un unsigned char es convertido a int con los bits más altos puestos a cero. Un signed char es convertido a int con los bits más altos puestos a uno o cero, dependiendo del valor de la variable.

Para los tipos de mayor tamaño: si un operando es de tipo double, el otro es convertido a double. Si un operando es de tipo float, el otro es convertido a float. Si un operando es de tipo unsigned long, el otro es convertido a unsigned long. Si un operando es de tipo long, el otro es convertido a long. Si un operando es de tipo unsigned, el otro es convertido a unsigned. Si no, los operandos son te tipo int.

Page 35: LENGUAJE en C

Una variable o expresión de un tipo se puede convertir explícitamente a otro tipo, anteponiéndole el tipo entre paréntesis.

cambio_tipo ()

{

float a;

int b;

b = 10;

a = 0.5;

if ( a <= (float) b )

menor();

}

Page 36: LENGUAJE en C

Control de flujo.

La sentencia de control básica es if (<e>) then <s> else <t>. En ella se evalúa una expresión condicional y si se cumple, se ejecuta la sentencia s; si no, se ejecuta la sentencia t. La segunda parte de la condición, else <t>, es opcional.

int cero ( double a )

{

if ( a == 0.0 )

return (TRUE);

else

return (FALSE);

}

Page 37: LENGUAJE en C

En el caso que <e> no sea una expresión condicional y sea aritmética, se considera falso si vale 0; y si no, verdadero. Hay casos en los que se deben evaluar múltiples condiciones y únicamente se debe evaluar una de ellas. Se puede programar con un grupo de sentencias if then else anidadas, aunque ello puede ser farragoso y de complicada lectura. Para evitarlo nos puede ayudar la sentencia switch. Su utilización es:

switch (valor)

{

case valor1: <sentencias>

case valor2: <sentencias>

...

default: <sentencias>

}

Page 38: LENGUAJE en C

Cuando se encuentra una sentencia case que concuerda con el valor del switch se ejecutan las sentencias que le siguen y todas las demás a partir de ahí, a no ser que se introduzca una sentencia break para salir de la sentencia switch. Por ejemplo,

ver_opcion ( char c )

{

switch(c)

{

case 'a': printf("Op A\n"); break;

case 'b': printf("Op B\n"); break;

case 'c':

case 'd': printf("Op C o D\n"); break;

default: printf("Op ?\n");

}

}

Page 39: LENGUAJE en C

Otras sentencias de control de flujo son las que nos permiten realizar iteraciones sobre un conjunto de sentencias. En C tenemos tres formas principales de realizar iteraciones. La sentencia while (<e>) <s> es seguramente la más utilizada. La sentencia, o grupo de sentencias <s> se ejecuta mientras la evaluación de la expresión <e> sea verdadera.

long raiz ( long valor )

{

long r = 1;

while ( r * r <= valor )

r++;

return r;

}

Page 40: LENGUAJE en C

Otra sentencia iterativa, que permite inicializar los controles del bucle se la sentencia for ( <i>; <e>; <p> ) <s>. La sentencia for se puede escribir también como:

<i>;

while ( <e> )

{

<s>;

<p>;

}

El ejemplo anterior se podría escribir como:

long raiz ( long valor )

{

long r;

for ( r = 1; r * r <= valor; r++ ) ;

return r;

}