Apuntes FPR IES Infiesto 1.6.– EXPRESIONES CONCEPTO: Una expresión es una combinación de uno o más operandos y operadores para obtener un resultado. Los operandos pueden ser constantes, variables, otras expresiones e incluso funciones. Se debe tener en cuenta el orden de prioridad y la asociatividad de los operadores para obtener un correcto resultado de la expresión COMPONENTES: 1) OPERANDOS: Son los objetos del lenguaje : variables, constantes, otras expresiones y funciones. 2) OPERADORES: Son símbolos que indican la operación o proceso a realizar con los operandos. RESULTADO: El resultado de evaluar una expresión es un determinado valor 1.7.– OPERADORES CONCEPTO: Son símbolos que indican la operación o proceso a realizar con los operandos de una expresión. Se evalúan siguiendo un orden preestablecido, denominado PRECEDENCIA, que es posible alterar, usando ciertos operadores específicos. Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto TIPOS: Existen tres clases generales de operadores en C: Aritméticos Relacionales y lógicos A nivel de bit Además C dispone de algunos operadores especiales para tareas particulares: Operadores de asignación Operadores incremento y decremento Operador condicional Operador coma Operadores especiales : ( ) y [ ] Operador sizeof Operador de dirección e indirección Operador molde o cast y CONVERSIONES DE TIPOS (implícitas y explícitas) 1.7.1– OPERADORES ARITMÉTICOS Sirven para realizar operaciones aritméticas básicas. Los operandos sobre los que actúan los operadores aritméticos deben representar valores numéricos. Por tanto, los operandos deben ser cantidades enteras, de coma flotante o caracteres. Son los siguientes: OPERADOR + * / % OPERACIÓN Suma Resta Producto División: si los operandos son enteros hace la división entera; en caso contrario devuelve decimales Módulo: resto de la división entera. Sólo funciona con enteros El operador módulo o resto de división entera (%), requiere que los dos operandos sean enteros y el segundo operando no nulo. La división de una cantidad entera por otra es denominada división entera. Esta operación siempre tiene como resultado el cociente entero Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto truncado. Por otra parte , si una operación de división se lleva a cabo con dos números de coma flotante, o con un número de coma flotante y un entero, el resultado será un cociente en coma flotante. Cuando los operandos difieren en el tipo pueden sufrir una conversión de tipo implícita antes de que la expresión alcance su valor final. En general, el resultado final se expresará con la mayor precisión posible, de forma consistente con los tipos de datos de los operandos. Se pueden aplicar las siguientes reglas de conversión: Primer operando Segundo operando Resultado Int Int Int Foat Double Double Long double Float/Double Long double Float Int/char float Double Int/char Double Long double Int/char Long double Short int Int Int Int Long int Long int Ejemplo: Supongamos que i es una variable entera, f una variable de coma flotante y c es una variable de tipo carácter. Se muestran a continuación las conversiones de tipo: i+f float i+c int i + c – ‘o’ int (i + c) – (2 * f / 5) float 1.7.2- OPERADORES RELACIONALES Estos operadores se utilizan para formar expresiones lógicas que representan condiciones que pueden ser ciertas o falsas. En concreto, permiten comparar valores: mayor que, menor que,…La expresión resultante será un número de tipo entero de forma que: si es falsa toma el valor 0 y si es verdadera toma cualquier valor distinto de 0 Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto Los operandos pueden ser de tipo: CARACTER, ENTERO, REAL o PUNTERO. Los operadores relacionales tiene menor prioridad que los aritméticos. Son: OPERADOR < <= > >= == != OPERACIÓN Menor que Menor o igual que Mayor que Mayor o igual que Igual a Distinto de Ejemplos de uso: int x, y, z; char m; x = 12; y = 5; m = ‘A’; 1) z = (x>y); 2) z = (x<y); 3) z = (x>89); 4) if (x>y) z=100; 5) z = (m < ‘J’); 6) z= (‘j’ > ‘k’); //z toma valor 1 (cierto) //z toma valor 0 (falso) //z toma valor 0 (falso) // z toma valor 100 porque x>y es cierto // z toma valor 1 (cierto) porque ‘A’<‘J’ // z toma valor 0 (falso) 1.7.3- OPERADORES LÓGICOS Estos operadores se utilizan para formar expresiones lógicas que representan condiciones que pueden ser ciertas o falsas. La expresión resultante será un número de tipo entero de forma que: si es falsa toma el valor 0 y si es verdadera toma cualquier valor distinto de 0 Los operadores relacionales tiene menor prioridad que los relacionales. Son: Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto OPERADOR && - || - ! - OPERACIÓN Es el AND lógico o Y La expresión que lo lleve será cierta, sólo cuando lo sean ambos operandos Es el OR lógico o O La expresión que lo lleve será cierta, si uno o ambos operandos lo son. Es el NOT lógico La expresión será cierta si el operando es falso y viceversa. Ejemplos de uso: int x, y; x = 12; y = 5; 1) z = (x && y); //z toma valor <>0 (cierto) 2) z = (x && 0); //z toma valor 0 (falso) 3) z = (x ||0); //z toma valor <> 0 (cierto) 4) if (x && y) z=100; // z toma valor 100 porque x&&y es cierto 5) z = !0; 6) z= !(1 || 0); // z toma valor <>0 (cierto) // z toma valor 0 (falso) 1.7.4- OPERADORES A NIVEL DE BITS Se usan para manipular bit a bit el operando, según la operación que se indique. Al manipular bit a bit son operadores de BAJO NIVEL equivalentes al ensamblador. SÓLO SE PUEDEN APLICAR a operandos enteros y char. NUNCA A float ni double. Son : Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto OPERADOR & - | ^ - ~ - >> - << - - OPERACIÓN Es el AND lógico bit a bit NO confundirlo con el operador unitario de dirección &". Es el OR lógico bit a bit Es el XOR u OR exclusivo bit a bit. Sólo es cierto cuando los dos operandos tienen valores opuestos o distintos.. Es el NOT bit a bit o COMPLEMENTO a 1. Desplazamiento a la derecha. Ej: x >> y desplaza a la derecha "y" bits de la variable "x". Equivale a dividir el nº x entre 2 elevado a y. Desplazamiento a la izquierda Ej: x << y desplaza a la izquierda "y" bits de la variable "x". Equivale a multiplicar el nº x por 2 elevado a y. Ejemplos de uso: int c, n; unsigned int mascara; 1) c = n & 0177; //hace el AND bit a bit entre el nº “n” y //el 0177 en octal (habría que pasar //ambos a binario) 2) c = n | 0177; //hace el OR bit a bit entre el nº “n” y el //0177 en octal 3) mascara = mascara << 3; //equivale a multiplicar //mascara por 2 elevado a 3 //(por 8) 4) c = 9 & 14 //c valdría 8, porque el AND bit a bit de // 9 en binario y 14 en binario es el nº 8 // en binario. 1.7.5- OPERADORES DE ASIGNACIÓN Se utilizan para asignar un valor a una variable, o para cargar una variable con el valor de una expresión. El formato es el siguiente: Identificador = expresión; Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto donde: Identificador: es el nombre de la variable. Expresión: es el valor que se le asigna a la variable, puede ser una constante, una variable o una expresión. Si los dos operandos de una sentencia de asignación son de diferente tipo de datos, el valor de la expresión de la derecha (el operador de la derecha) se convertirá automáticamente al tipo del identificador de la izquierda. En C están permitidas asignaciones múltiples de la forma: identificador1 = identificador2 = ... = expresión; Por ejemplo: a = b = c = 5; El lenguaje C también del OPERADOR DE ASIGNACIÓN COMPUESTO que utiliza dos símbolos, uno es el de asignación simple y el otro es un símbolo de operación. Su formato es el siguiente: OPERADOR += - -= - *= - /= - %= - - Profesora: Mª Alejandra Tomás Fdez OPERACIÓN Suma el valor de la expresión situada en el lado derecho con la variable situada en la izquierda. Ejemplo: x += 13 es equivalente a: x = x + 13 Resta el valor de la expresión situada en el lado derecho, de la variable situada en la izquierda. Ejemplo: x -= y es equivalente a x=x-y Multiplica el valor de la expresión situada a la derecha del operador, por la variable situada a la izquierda. Ejemplo: x *=y es equivalente a x = x * y Divide el valor de la variable situada a la izquierda del símbolo, entre la expresión situada a la derecha. Ejemplo: x/=y es equivalente a x = x / y Devuelve el resto de la división de la variable situada a la izquierda entre el valor de la expresión de la derecha. Ejemplo: x %= y es equivalente a x=x % y Apuntes FPR IES Infiesto 1.7.6- OPERADORES DECREMENTO INCREMENTO Y Sirven para incrementar o decrementar el valor de una variable de uno en uno. Son: OPERADOR ++ -- OPERACIÓN incremento Decremento Se pueden utilizar tanto el ++ como el – de 2 formas distintas dependiendo de dónde se escriba el operador: a) Si se escribe ++ o – antes del operando (por ejemplo: ++i), es decir, como prefijo, el valor del operando se modificará antes de que se use con otro propósito. Ejemplo: int a,b,c; a = 3; b = ++a; // 1º) incrementa 1 a la “a” y pasa a valer 4 // 2º) asigna el 4 a b c = ++a *2; // 1º) incrementa 1 a la “a” y pasa a valer 5 // 2º) hace 5*2 que es 10 y // 3º) asigna 10 a “c” b) Sin embargo, si el operador ++ o – sigue al operando (por ejemplo i++), entonces, el valor del operando se modificará después de ser usado. Ejemplo: int a,b,c; a = 3; b = a++; //1º) asigna 3 a “b” y // 2º) incrementa 1 a la “a” y pasa a valer 4 c = a++ *2; //1º) hace “a*2” que como “a” vale 4 obtiene 8, //2º) asigna 8 a c y, //3º) incrementa 1 a “a” que pasa a valer 5 Ejemplos varios de uso: A ) Supongamos que tenemos una variable i de tipo entero con valor 5. Si tenemos las siguientes instrucciones: Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto escribir (i); escribir (++i); escribir (i); el resultado será 5, 6, 6. Sin embargo, si tenemos las siguientes instrucciones escribir (i); escribir (i++); escribir(i); el resultado será 5, 5, 6. B ) Si tenemos: int a, b, c; a = 10; b = a--; //hace b=10 y a = 9 en ese orden c = a++ * --b; // hace “a * --b” y luego incrementa a. Es decir , //hace 9 * 9 y luego hace a = 10 a=--b; // hace b=8 porque lo decrementa y luego a = 8 1.7.7- OPERADOR CONDICIONAL Es un operador que se utiliza para sustituir a la sentencia IF-ELSE (es la sentencia SI-ENTONCES-SINO del pseudocódigo) en determinadas situaciones. Es un operador TERNARIO, es decir, lleva 3 operandos. Su formato es el siguiente: Expresión condicion ? Expresion1 : Expresion2; El funcionamiento es el siguiente: Se evalúa la expresión condicional, si esta se cumple entonces se evalúa Expresion1 y si no se cumple se evalúa Expresion2. Ejemplos: 1) (ventas>1500) ? comision=100 : comision=0 Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto Lo que hace es: “pone comision a 100 si las ventas>1500. Sino pone comision a 0”. Equivale a: if (ventas>1500) SI ventas>1500 ENTONCES comision=100; else comision=100; SINO comision=0; comision=0; FINSI 2) n >=0 ? 1 : -1 Lo que hace es: “devuelve 1 si n>=0 y -1 en otro caso”. Equivale a: if (n>=0) SI n>=0 ENTONCES return 1; else RETORNAR 1 SINO return -1; RETORNAR -1 FINSI 3) m >= n ? m : n Lo que hace es: “devuelve m si m>=n y n en otro caso”. Equivale a: if (m>=n) SI m>=n ENTONCES return m; else RETORNAR m SINO return n; RETORNAR n FINSI Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto 1.7.8- OPERADOR COMA Es un operador que se utiliza para combinar 2 o más expresiones en una misma línea. Su sintaxis es: expresion1, expresion2, ... expresion_n Y su funcionamiento sería el siguiente: “Primer se evalúa expresion1 , luego la expresion2; y así sucesivamente hasta la expresion_n”. Ejemplos: 1) x = (y=3, y+1) Equivale a: y = 3; x = y+1; 2) y = 10; x = (y = y –5, 25/y); Equivale a: y = 10; y = y-5; x = 25/y; 3) int i=10, j=24; //da el valor 10 a la i y el valor 24 a la j 4) i = 10; j = (i = 12, i + 8); Equivale a: i = 10; i = 12; j=i+8; 5) for (i=0, j=1; i<20; i++) //inicializa la i a 0 y la j a 1 1.7.9- OPERADORES ESPECIALES: ( ) y [ ] PARÉNTESIS ( ): Es un operador que se utiliza para diferentes tareas como son: 1) Encerrar los argumentos de una función. Ejemplo: Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto pow(2,3); 2) Efectuar conversiones explícitas de tipo. Ejemplo: precio_entero = (int) 13.65; 3) Resolver conflictos de prioridades entre operadores. Ejemplo: y =(2 + 3) *8; 4) Indicar, dentro de una declaración, que un identificador corresponde a una función. CORCHETES [ ]: Es un operador que se utiliza para designar un elemento de un array o vector o cadena de caracteres o para declarar dichos objetos. Ejemplos: 1) char cadena[50]; 2) int v[15], i; i=3; v[i]=34; 1.7.10- OPERADOR sizeof Se usa para calcular el tamaño del operando que se le pasa en bytes. El operando puede ser: a) el nombre de un tipo de datos. Ejemplo: sizeof (double); b) el nombre de una variable. Ejemplo: int a; sizeof (a); c) una expresión. Ejemplo: int a, b; sizeof (a+b); Ejemplos: 1) printf (“ el tipo int ocupa %d bytes\n”, sizeof (int)); 2) printf (“el tipo char ocupa %d bytes\n”, sizeof (char)); Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto 3) printf (“el tipo float ocupa %d bytes\n”, sizeof (float)); 4) printf (“el tipo unsigned ocupa %d bytes\n”, sizeof (unsigned)); 1.7.11- OPERADORES DIRECCIÓN e INDIRECCIÓN Operador DIRECCIÓN (&): Este operador da la dirección de memoria de su operando. Es un operador unario, sólo lleva 1 operando. No se puede aplicar a una variable declarada como register pues estas variables no tienen direcciones de memoria, ya que se almacenan en registros físicos del micro. Ejemplos: 1) int *b; int a; b = &a; 2) float d,*c; c = &d; //b es de tipo puntero y guardará la dirección de // memoria de la variable a //c es de tipo puntero a float y guardará la // dirección de memoria de la variable d. Operador INDIRECCIÓN (*): Este operador accede al contenido de una INDIRECTAMENTE, a través de un puntero. El puntero contiene la dirección de memoria de una variable. Y con este operador accedemos al contenido de esa variable, PERO a través del puntero Es un operador unario, sólo lleva 1 operando. Ejemplo: int *a; int c,b; b = 23; a =&b; c= *a; Profesora: Mª Alejandra Tomás Fdez variable // a es un puntero a entero. Contendrá una // dirección de una variable de tipo entero. // b es una variable de tipo entero // asigno el valor 23 a b // asigno la dirección de b al puntero a. //Con lo cual, el puntero a está apuntando a b. // asigno a la variable c 23 (el contenido de b) Apuntes FPR IES Infiesto // Realmente estoy asignando a c el contenido de la // variable a la cual apunta “a”. Pero, ¿ a quien apunta // “a”???. Respuesta: apunta a “b”. Por tanto, estoy // asignando el 23. 1.7.12- OPERADOR TIPOS MOLDE. CONVERSIÓN DE A veces, se necesita convertir el tipo de un dato de un tipo determinado a otro tipo sin cambiar su valor. Por ejemplo: un entero convertirlo en real, un char en entero, ...a esto se le denomina CONVERSIÓN DE TIPOS. FORMAS DE CONVERSIÓN DE TIPOS EN C: a) Conversiones Implícitas: • Son conversiones que ejecuta AUTOMÁTICAMENTE el compilador. • C hace conversiones automáticas en los siguientes casos: I. Cuando se asigna un valor de un tipo a una variable de otro tipo. Ejemplo: int a; float b; b = 4; //transforma el 4 entero en 4.0 float II. Cuando se combinan tipos mixtos en expresiones. Ejemplo: int a,c; float b; c = a + b; //convierte b a entero y opera III. Cuando se pasan argumentos a funciones. • ¿Cómo hace las conversión IMPLÍCITAS el C?: 1) En una operación con operandos de distintos tipos, el operando de tipo inferior es convertido al de tipo superior, antes de operar y luego se realiza ya la operación. Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto 2) Cuando se asigna un valor de un tipo a una variable de otro tipo, ese valor se convierte al tipo de la variable de la siguiente forma: a) Si la variable es de tipo superior (más preciso) al valor, la conversión es la indicada en el punto 1) y no se pierde información. Por ejemplo un int se convierte a float, un float a double,... Ej: float b; b = 4; // 4 se convierte de entero a 4.0 (float) b) Si la variable es de tipo inferior al valor (por ejemplo un float a int), la conversión se hace del tipo superior al inferior, PERO SE PIERDE INFORMACIÓN. Ej: int a; a = 4.5; //4.5 se convierte a 4 y se pierde .5 b) Conversiones Explícitas (Operador molde o CAST): • Consiste en forzar la conversión del tipo de dato de una expresión mediante el uso del OPERADOR DE MOLDE o CAST. • La sintaxis del operador de molde es: (nombre_tipo) expresión donde la expresión es convertida al tipo cuyo nombre se indica, siguiendo las reglas de conversión expuestas en el apartado de “conversión implícita”. • Ejemplos: 1) 2) 3) Profesora: Mª Alejandra Tomás Fdez int i; (float) i; // convierte i a float precio_entero = (int) 15.36 + (int) 56.4 // suma 15 + 56 int peso, altura; float salud; peso = 70; altura = 175; salud = (float) (altura / peso); // 1º) hace 175/70 = 2 porque la división de 2 Apuntes FPR IES Infiesto //enteros en C es división entera, sin decimales. Y //2º) convierte 2 a float, es decir, le pone 2.0 1.7.13- PRIORIDAD O PRECEDENCIA DE LOS OPERADORES Los operadores de C se agrupan jerárquicamente de acuerdo con su precedencia (su orden de evaluación). Las operaciones con mayor precedencia se realizan antes que las operaciones que tienen menor precedencia. Sin embargo se puede alterar el orden natural de evaluación mediante el uso de paréntesis. Otra cosa importante a considerar es el orden en que se realizarán operaciones consecutivas del mismo grupo de precedencia. Esto se conoce como asociatividad. Dentro de cada uno de los grupos de precedencia, la asociatividad suele ser de izquierda a derecha. En otras palabras, operaciones consecutivas de adición y sustracción, por ejemplo, se realizarán de izquierda a derecha, así como operaciones consecutivas de multiplicación, división y resto. Sin embargo, a veces, la asociatividad es de derecha a izquierda; por ejemplo, en el caso de lo operadores unarios, el operador condicional y los de asignación. La siguiente tabla refleja el orden de prioridad de los operadores de mayor prioridad a menos junto con su asociatividad: Operador -> . () [] ! + ++ -* & (tipo dato) sizeof * / % + << >> Profesora: Mª Alejandra Tomás Fdez Significado Operador flecha Operador punto Paréntesis Corchetes No lógico Signo menos (no la resta) Signo más (no la suma) Incremento Decremento Operador indirección Operador dirección Operador Molde o cast Operador tamaño Multiplicación División Módulo Suma Resta Operadores de desplazamiento de BIT a BIT Asociatividad De izquierda a derecha De izquierda a derecha Los más internos. Los más internos Derecha a izquierda. Izquierda a derecha Izquierda a derecha Izquierda a derecha Apuntes FPR IES Infiesto < <= > >= == != & ^ | && || ?: = += -= *= /= %= , Menor que Menor o igual que Mayor que Mayor o igual que Igual a Distinto de AND BIT a BIT XOR BIT a BIT OR BIT a BIT AND OR Operador condicional Asignación Izquierda a derecha Izquierda a derecha Izquierda a derecha Izquierda a derecha Izquierda a derecha Izquierda a derecha Izquierda a derecha Derecha a izquierda Coma Derecha a izquierda. Izquierda a derecha 1.8.– SENTENCIAS DE ENTRADA y SALIDA Las operaciones de entrada y salida (abreviadamente E/S) no forman parte del lenguaje C propiamente dicho, sino que existen una serie de funciones ya hechas que manejan las operaciones de E/S y que están en una biblioteca o librería: <stdio.h>. Por tanto, todo programa que utilice funciones de entrada y salida estándar deberá contener la línea: #include <stdio.h> En C, los programas se comunican con el exterior a través de FLUJOS (streams). Conceptualmente, UN FLUJO es una ristra de bytes que se puede ir leyendo o sobre la que se puede escribir caracteres. Un flujo puede ser un fichero ordinario, o estar asociado a un dispositivo. Cuando se lee del teclado es porque previamente se ha abierto como flujo de caracteres del que leer. Un programa, cuando muestra algo por pantalla, está escribiendo caracteres a un flujo de salida. En C, cualquier cosa externa de la que podemos leer o en la que podemos escribir datos es un fichero. El programador escribe (lee) datos en estos ficheros a través de los flujos de cada fichero. De esta forma el programador escribe (lee) los datos de la Profesora: Mª Alejandra Tomás Fdez Apuntes FPR IES Infiesto misma forma en todos los tipos de ficheros independientemente del tipo de fichero que sea. En C se tienen predefinidos 3 flujos (en stdio.h): stdin (entrada estándar), stdout (salida estándar) y stderr (flujo de errores estándar). FLUJO stdin: El flujo stdin es la ENTRADA ESTÁNDAR. Suele estar asociado, por defecto, con el dispositivo TECLADO. Pero, puede ser usado con archivos, programas, dispositivos de E/S como el teclado, pantalla, ... mediante REDIRECCIÓN. FLUJO stdout: El flujo stdout es la SALIDA ESTÁNDAR. Suele estar asociado, por defecto, con el dispositivo PANTALLA. Pero, puede ser usado con archivos, programas, dispositivos de E/S como el teclado, la pantalla,... mediante REDIRECCIÓN. FLUJO stderr: El flujo stderr es el flujo de ERROR ESTÁNDAR. Es el flujo donde se vierten los mensajes de error. Habitualmente coincide con la SALIDA ESTÁNDAR, pero se considera un flujo diferente. Siempre está asociado con el dispositivo PANTALLA. ESTOS 3 FLUJOS ESTÁNDAR: stdin, stdout AUTOMÁTICAMENTE ABIERTOS. Profesora: Mª Alejandra Tomás Fdez y stderr, SON