Manipulando datos (Operadores)

Curso de C

Contenido del capítulo

¿Qué es un operador?

Un operador sirve para manipular datos. Los hay de varios tipos: de asignación, de relación, lógicos, aritméticos y de manipulación de bits. En realidad los nombres tampoco importan mucho; aquí lo que queremos es aprender a programar, no aprender un montón de nombres.

[Arriba]

Operador de asignación

Este es un operador que ya hemos visto en el capítulo de Tipos de Datos. Sirve para dar un valor a una variable. Este valor puede ser un número que tecleamos directamente u otra variable:

	a = 3;		/* Metemos un valor directamente */
o
	a = b;		/* Le damos el valor de una variable */

Podemos dar valores a varias variables a la vez:

	a = b = c = 10;		/* Damos a las variables a,b,c el valor 10 */

También podemos asignar a varias variables el valor de otra de un sólo golpe:

	a = b = c = d;		/* a,b,c toman el valor de d */

[Arriba]

Operadores aritméticos

Los operadores aritméticos son aquellos que sirven para realizar operaciones tales como suma, resta, división y multiplicación.

Si quieres saber cómo usar funciones matemáticas más complejas (exponentes, raíces, trigonométricas) vete al capítulo correspondiente.

[Arriba]

Operador (+) : Suma

Este operador permite sumar variables:

	#include <stdio.h>

	int main()
		{
		int a = 2;
		int b = 3;
		int c;

		c = a + b;
		printf ( "Resultado = %i\n", c );
		}

El resultado será 5 obviamente.

Por supuesto se pueden sumar varias variables o variables más constantes:

	#include <stdio.h>

	int main()
		{
		int a = 2;
		int b = 3;
		int c = 1;
		int d;

		d = a + b + c + 4;
		printf ( "Resultado = %i\n", c );
		}

El resultado es 10.

Podemos utilizar este operador para incrementar el valor de una variable:

	x = x + 5;

Pero existe una forma abreviada:

	x += 5;

Esto suma el valor 5 al valor que tenía la variable x. Veamos un ejemplo:

	#include <stdio.h>

	int main()
		{
		int x, y;

		x = 3;
		y = 5;

		x += 2;
		printf( "x = %i\n", x );
		x += y;		/* esto equivale a x = x + y */
		printf( "x = %i\n", x );
		}

Resultado:

	x = 5
	x = 10

[Arriba]

Operador (++) : Incremento

Este operador equivale a sumar uno a la variable:

	#include <stdio.h>

	int main()
		{
		int x = 5;

		printf ( "Valor de x = %i\n", x );
		x++;
		printf ( "Valor de x = %i\n", x );
		}

Resultado:

	Valor de x = 5
	Valor de x = 6

Se puede poner antes o después de la variable.

[Arriba]

Operador (-) : Resta/Negativo

Este operador tiene dos usos, uno es la resta que funciona como el operador suma y el otro es cambiar de signo.

Resta:

	x = x - 5;

Para la operación resta se aplica todo lo dicho para la suma. Se puede usar también como: x -= 5;.

Pero también tiene el uso de cambiar de signo. Poniendolo delante de una variable o constante equivale a multiplicarla por -1.

	#include <stdio.h>

	int main()
		{
		int a, b;

		a = 1;

		b = -a;
		printf( "a = %i, b = %i\n", a, b );
		}

Resultado: a = 1, b = -1. No tiene mucho misterio.

[Arriba]

Operador (--) : Decremento

Es equivalente a ++ pero en vez de incrementar disminuye el valor de la variable. Equivale a restar uno a la variable.

[Arriba]

Operador (*) : Multiplicación y punteros

Este operador sirve para multiplicar y funciona de manera parecida a los anteriores.

También sirve para definir y utilizar punteros, pero eso lo veremos más tarde.

[Arriba]

Operador (/) : División

Este funciona también como los anteriores pero hay que tener cuidado. Si dividimos dos número en coma flotante (tipo float) tenemos las división con sus correspondientes decimales. Pero si dividimos dos enteros obtenemos un número entero. Es decir que si dividimos 4/3 tenemos como resultado 1. El redondeo se hace por truncamiento, simplemente se eliminan los decimales y se deja el entero.

Si dividimos dos enteros el resultado es un número entero, aunque luego lo saquemos por pantalla usando %f o %d no obtendremos la parte decimal.

Cuando dividimos dos enteros, si queremos saber cual es el resto (o módulo) usamos el operador %, que vemos más abajo.

[Arriba]

Operador (%) : Resto

Si con el anterior operador obteníamos el módulo o cociente de una división entera con éste podemos tener el resto. No funciona más que con enteros, no vale para números float o double.

Cómo se usa:

	#include <stdio.h>

	int main()
		{
		int a, b;

		a = 18;
		b = 5;
		printf( "Resto de la división: %d \n", a % b );
		}

[Arriba]

Operadores de comparación

Los operadores de condición se utilizan para comprobar las condiciones de las sentencias de control de flujo (las estudiaremos en el capítulo sentencias).

Cuando se evalúa una condición el resultado que se obtiene es 0 si no se cumple y un número distinto de 0 si se cumple. Normalmente cuando se cumplen devuelven un 1.

Los operadores de comparación son:

== igual que se cumple si son iguales
!= distinto que se cumple 1 si son diferentes
> mayor que se cumple si el primero es mayor que el segundo
< menor que se cumple si el primero es menor que el segundo
>= mayor o igual que se cumple si el primero es mayor o igual que el segundo
<= menor o igual que se cumple si el primero es menor o igual que el segundo

Veremos la aplicación de estos operadores en el capítulo Sentencias. Pero ahora vamos a ver unos ejemplos:

	#include <stdio.h>

	int main()
		{
		printf( "10 > 5 da como resultado %i\n", 10>5 );
		printf( "10 > 5 da como resultado %i\n", 10>5 );
		printf( "5== 5 da como resultado %i\n", 5==5 );
		printf( "10==5 da como resultado %i\n", 10==5 );
		}

No sólo se pueden comparar constantes, también se pueden comparar variables.

[Arriba]

Operadores lógicos

Estos son los que nos permiten unir varias comparaciones: 10>5 y 6==6. Los operadores lógicos son: AND (&&), OR (||), NOT(!).

Operador && (AND, en castellano Y): Devuelve un 1 si se cumplen dos condiciones.

	printf( "Resultado: %i", (10==10 && 5>2 );

Operador || (OR, en castellano O): Devuelve un 1 si se cumple una de las dos condiciones.

Operador ! (NOT, negación): Si la condición se cumple NOT hace que no se cumpla y viceversa.

Ver el capítulo Sentencias, sección Notas sobre las condiciones para más información.

[Arriba]

Introducción a los bits y bytes

En esta sección voy a describir lo que son los bytes y los bits. No voy a descubrir nada nuevo, así que la mayoría se podrán saltar esta sección.

Supongo que todo el mundo sabe lo que son los bytes y los bits, pero por si acaso allá va. Los bits son la unidad de información más pequeña, digamos que son la base para almacenar la información. Son como los átomos a las moléculas. Los valores que puede tomar un bit son 0 ó 1. Si juntamos ocho bits tenemos un byte.

Un byte puede tomar 256 valores diferentes (de 0 a 255). ¿Cómo se consigue esto? Imaginemos nuestro flamante byte con sus ocho bits. Supongamos que los ocho bits valen cero. Ya tenemos el valor 0 en el byte. Ahora vamos a darle al último byte el valor 1.

00000001 -> 1

Este es el uno para el byte. Ahora vamos a por el dos y el tres:

00000010 -> 2
00000011 -> 3

y así hasta 255. Como vemos con ocho bits podemos tener 256 valores diferentes, que en byte corresponden a los valores entre 0 y 255.

[Arriba]

Operadores de bits

Ya hemos visto que un byte son ocho bits. Pues bien, con los operadores de bits podemos manipular las variables por dentro. Los diferentes operadores de bits son:

Operador Descripción
| OR (O)
& AND (Y)
^ XOR (O exclusivo)
~ Complemento a uno o negación
>> Desplazamiento a la derecha
<< Desplazamiento a la izquierda

Operador | (OR):

Toma los valores y hace con ellos la operación OR. Vamos a ver un ejemplo:

	#include <stdio.h>

	int main()
		{
		printf( "El resultado de la operación 235 | 143 es: %i\n", 235 | 143 );
		}

Se obtiene:

El resultado de la operación 235 | 143 es: 239

Veamos la operación a nivel de bits:

	235 -> 11101011
	143 -> 10001111 |
	239 -> 11101111

La operación OR funciona de la siguiente manera: Tomamos los bits dos a dos y los comparamos si alguno de ellos es uno, se obtiene un uno. Si ambos son cero el resultado es cero. Primero se compara los dos primeros (el primero de cada uno de los números, 1 y 1 -> 1), luego la segunda pareja (1 y 0 -> 1) y así sucesivamente.

Operador & (AND):

Este operador compara los bits también dos a dos. Si ambos son 1 el resultado es 1. Si no, el resultado es cero.

	#include <stdio.h>

	int main()
		{
		printf( "El resultado de la operación 170 & 155 es: %i\n", 170 & 155 );
		}

Tenemos:

El resultado de la operación 170 & 155 es: 138

A nivel de bits:

	170 -> 10101010
	155 -> 10011011 &
	138 -> 10001010

Operador ^ (XOR):

Compara los bits y los pone a unos si son distintos.

	235 -> 11101011
	143 -> 10001111 ^
	100 -> 01100100

Operador ~ (Complemento a uno):

Este operador acepta un sólo dato (operando) y pone a 0 los 1 y a 1 los 0, es decir los invierte. Se pone delante del operando.

	#include <stdio.h>

	int main()
		{
		printf( "El resultado de la operación ~152 es: %i\n", ~152 );
		}

El resultado de la operación ~152 es: 103
	152 -> 10011000 ~
	103 -> 01100111

Operador >> (Desplazamiento a la derecha):

Este operador mueve cada bit a la derecha. El bit de la izquierda se pone a cero, el de la derecha se pierde. Si realizamos la operación inversa no recuperamos el número original. El formato es:

	variable o dato >> número de posiciones a desplazar

El número de posiciones a desplazar indica cuantas veces hay que mover los bits hacia la derecha. Ejemplo:

	#include <stdio.h>

	int main()
		{
		printf( "El resultado de la operación 150 >> 2 es: %i\n", ~152 );
		}

El resultado de la operación 150 >> 2 es: 37

Veamos la operación paso a paso. Esta operación equivale a hacer dos desplazamientos a la derecha:

	150 -> 10010110  Número original
	 75 -> 01001011 Primer desplazamiento. Entra un cero por la izquierda,
			el cero de la derecha se pierde y los demás se mueven a la derecha.
	 37 -> 00100101 Segundo desplazamiento.

NOTA: Un desplazamiento a la izquierda equivale a dividir por dos. Esto es muy interesante porque el desplazamiento es más rápido que la división. Si queremos optimizar un programa esta es una buena idea. Sólo sirve para dividir entre dos. Si hacemos dos desplazamientos sería dividir por dos dos veces, no por tres.

Operador << (Desplazamiento a la izquierda):

Funciona igual que la anterior pero los bits se desplazan a la izquierda. Esta operación equivale a multiplicar por 2.

[Arriba]

Operador Sizeof

Este es un operador muy útil. Nos permite conocer el tamaño en bytes de una variable. De esta manera no tenemos que preocuparnos en recordar o calcular cuanto ocupa. Además el tamaño de una variable cambia de un compilador a otro, es la mejor forma de asegurarse. Se usa poniendo el nombre de la variable después de sizeof y separado de un espacio:

	#include <stdio.h>

	int main()
		{
		int variable;

		printf( "Tamaño de la variable: %i\n", sizeof variable );
		}

Tambíen se puede usar con los especificadores de tipos de datos (char, int, float, double...). Pero en éstos se usa de manera diferente, hay que poner el especificador entre paréntesis:

	#include <stdio.h>

	int main()
		{
		printf( "Las variables tipo int ocupan: %i\n", sizeof(int) );
		}

[Arriba]

Otros operadores

Existen además de los que hemos visto otros operadores. Sin embargo ya veremos en sucesivos capítulos lo que significa cada uno.

[Arriba]

Orden de evaluación de Operadores

Debemos tener cuidado al usar operadores pues a veces podemos tener resultados no esperados si no tenemos en cuenta su orden de evaluación. Vamos a ver la lista de precedencias, cuanto más arriba se evalúa antes:

Precedencia
() [] -> .
! ~ ++ -- (molde) * & sizeof (El * es el de puntero)
* / % (El * de aquí es el de multiplicación)
+ -
<< >>
< <= > >=
== !=
&
^
|
&&
||
?:
= += -= *= /=
,

Por ejemplo imaginemos que tenemos la siguiente operación:

	10 * 2 + 5

Si vamos a la tabla de precedencias vemos que el * tiene un orden superior al +, por lo tanto primero se hace el producto 10*2=20 y luego la suma 20+5=25. Veamos otra:

	10 * ( 2 + 5 )

Ahora con el paréntesis cambia el orden de evaluación. El que tiene mayor precedencia ahora es el paréntesis, se ejecuta primero. Como dentro del paréntesis sólo hay una suma se evalúa sin más, 2+5=7. Ya solo queda la multiplicación 10*7=70. Otro caso:

	10 * ( 5 * 2 +3 )

Como antes, el que mayor precedencia tiene es el paréntesis, se evalúa primero. Dentro del paréntesis tenemos producto y suma. Como sabemos ya se evalúa primero el producto, 5*2=10. Seguimos en el paréntesis, nos queda la suma 10+3=13. Hemos acabado con el paréntesis, ahora al resto de la expresión. Cogemos la multiplicación que queda: 10*13=130.

Otro detalle que debemos cuidar son los operadores ++ y --. Estos tienen mayor precedencia que las demás operaciones aritméticas (+, -, *, /, %). Por ejemplo:

	10 * 5 ++

Puede parecer que primero se ejecutará la multiplicación y luego el ++. Pero si vamos a la tabla de precedencias vemos que el ++ está por encima de * (de multiplicación), por lo tanto se evaluará primero 5++=6. 10*6=60.

Es mejor no usar los operadores ++ y -- mezclados con otros, pues a veces obtenemos resultados inesperados. Por ejemplo:

	#include <stdio.h>

	int main()
		{
		int a, b;

		a = 5;
		b = a++;
		printf( "a = %i, b = %i\n", a, b );
		}

Este ejemplo en unos compiladores dará a = 6, b = 5 y en otros a = 6 y b = 6. Por favor si podeis, escribidme diciendo qué valores os salen a vosotros y qué compilador usais.

Para asegurarse lo mejor sería separar la línea donde se usa el ++ y el =:

	#include <stdio.h>

	int main()
		{
		int a, b;

		a = 5;
		a++;
		b = a;
		printf( "a = %i, b = %i\n", a, b );
		}

[Arriba]

Ejercicios

Ejercicio 1: En este programa hay un fallo muy gordo y muy habitual en programación. A ver si lo encuentras:

	#include <stdio.h>

	int main()
		{
		int a, c;

		a = 5;
		c += a +5;
		}

Solución:

Cuando calculamos el valor de 'c' sumamos a+5 ( =10 ) al valor de 'c'. Pero resulta que 'c' no tenía ningún valor indicado por nosotros. Estamos usando la variable 'c' sin haberle dado valor. En algunos compiladores el resultado será inesperado. Este es un fallo bastante habitual, usar variables a las que no hemos dado ningún valor.

Ejercicio 2: ¿Cual será el resultado del siguiente programa?

#include <conio.h>
#include <stdio.h>

int main()
     {
     int a, b, c;

     a = 5;
     b = ++a;
     c = ( a + 5 * 2 ) * ( b + 6 / 2 ) + ( a * 2 );
     printf( "%i, %i, %i", a, b, c );
     }

Solución:

El resultado es 156. En la primera a vale 5. Pero en la segunda se ejecuta b = ++a = ++5 = 6. Tenemos a = b = 6.

Ejercicio 3: Escribir un programa que compruebe si un número es par o impar.

Solución:

#include <stdio.h>

int main() {
    char palabra[100];
    int a;

    a = 124;
    if ( a % 2 == 0 )
        printf( "%d es par\n", a );
    else
        printf( "%d es impar\n", a );
    printf( "\n" );
    system( "pause" );
    return 0;
}

Fichero: cap5_ejercicio3.c

Para comprobar si un número es par o impar podemos usar el operador '%'. Si al calcular el resto de dividir un número por 2 el resultado es cero eso indica que el número es par. Si el resto es distinto de cero el número es impar.

[Arriba]

[Anterior] [Siguiente] [Contenido]


Contenido del curso:


© Gorka Urrutia, 1999-2016