18 Operadores IV: Más operadores

Alguien dijo una vez que C prácticamente tiene un operador para cada instrucción de ensamblador. De hecho C y mucho más C++ tiene una enorme riqueza de operadores, éste es el tercer capítulo dedicado a operadores, y aún nos quedan más operadores por ver.

Operadores de bits

Estos operadores trabajan con las expresiones que manejan manipulándolas a nivel de bit, y sólo se pueden aplicar a expresiones enteras. Existen seis operadores de bits, cinco binarios y uno unitario: "&", "|", "^", "~", ">>" y "<<".

Sintaxis:

<expresión> & <expresión>
<expresión> ^ <expresión>
<expresión> | <expresión>
~<expresión>
<expresión> << <expresión>
<expresión> >> <expresión>

El operador "&" corresponde a la operación lógica "AND", o en álgebra de Boole al operador "·", compara los bits uno a uno, si ambos son "1" el resultado es "1", en caso contrario "0".

El operador "^" corresponde a la operación lógica "OR exclusivo", compara los bits uno a uno, si ambos son "1" o ambos son "0", el resultado es "0", en caso contrario "1".

El operador "|" corresponde a la operación lógica "OR", o en álgebra de Boole al operador "+", compara los bits uno a uno, si uno de ellos es "1" el resultado es "1", en caso contrario "0".

El operador "~", (se obtiene con la combinación de teclas ALT+126, manteniendo pulsada la tecla "ALT", se pulsan las teclas "1", "2" y "6" del teclado numérico, o bien con la combinación de teclas AltGr+4 seguido de un espacio), corresponde a la operación lógica "NOT", se trata de un operador unitario que invierte el valor de cada bit, si es "1" da como resultado un "0", y si es "0", un "1".

El operador "<<" realiza un desplazamiento de bits a la izquierda del valor de la izquierda, introduciendo "0" por la derecha, tantas veces como indique el segundo operador; equivale a multiplicar por 2 tantas veces como indique el segundo operando.

El operador ">>" realiza un desplazamiento de bits a la derecha del valor de la izquierda, introduciendo "0" por la izquierda, tantas veces como indique el segundo operador; equivale a dividir por 2 tantas veces como indique el segundo operando.

Tablas de verdad:

Operador 1 Operador 2 AND OR exclusivo OR inclusivo NOT
E1
E2
E1 & E2
E1 ^ E2
E1 | E2
~E1
0
0
0
0
0
1
1
0
0
1
1
0
0
1
0
1
1
1
1
1
1
0
1
0

Ya hemos visto que los operadores '~', '&', '<<' y '>>' tienen otras aplicaciones diferentes, su funcionamiento es contextual, es decir, se decide después del análisis de los operandos. En C++ se conoce esta reutilización de operadores como sobrecarga de operadores o simplemente sobrecarga, más adelante introduciremos un capítulo dedicado a este tema.

Ejemplos

Espero que estés familiarizado con la numeración hexadecimal, ya que es vital para interpretar las operaciones con bits.

De todos modos, no es demasiado complicado. Existe una correspondencia directa entre los dígitos hexadecimales y combinaciones de cuatro dígitos binarios, veamos una tabla:

Hexadecimal Binario Hexadecimal Binario
0
0000
8
1000
1
0001
9
1001
2
0010
A
1010
3
0011
B
1011
4
0100
C
1100
5
0101
D
1101
6
0110
E
1110
7
0111
F
1111
int a, b, c;
 
a = 0xd3; // = 11010011
b = 0xf5; // = 11110101
c = 0x1e; // = 00011110
 
d = a | b; // 11010011 | 11110101 = 11110111 -> 0xf7
d = b & c; // 11110101 & 00011110 = 00010100 -> 0x14
d = a ^ c; // 11010011 ^ 00011110 = 11001101 -> 0xcd
d = ~c;    // ~00011110 = 11100001 -> 0xe1
d = c << 3 // 00011110 << 3 = 11110000 ->; 0xf0
d = a >> 4 // 11010011 >> 4 = 00001101 ->; 0x0d

Operador condicional

El operador "?:", se trata de un operador ternario.

Sintaxis:

<expresión lógica> ? <expresión> : <expresión>

En la expresión E1 ? E2 : E3, primero se evalúa la expresión E1, si el valor es verdadero (true), se evaluará la expresión E2 y E3 será ignorada, si es falso (false), se evaluará E3 y E2 será ignorada.

Hay ciertas limitaciones en cuanto al tipo de los argumentos.

  • E1 debe ser una expresión lógica.

E2 y E3 han de seguir una de las siguientes reglas:

  • Ambas de tipo aritmético.
  • Ambas de estructuras o uniones compatibles.
  • Ambas de tipo void.

Hay más reglas, pero las veremos más adelante, ya que aún no hemos visto nada sobre los conocimientos implicados.

Como ejemplo veremos cómo se puede definir la macro "max":

#define max(a,b) (((a) > (b)) ? (a) : (b))

De este ejemplo sólo nos interesa la parte de la derecha. La interpretación es: si "a" es mayor que "b", se debe evaluar "a", en caso contrario evaluar "b".

Otros ejemplos prácticos:

Cuando el número a mostrar sea uno, el texto será un singular "elemento", si es otro número, será el plural "elementos".

    cout << "Tenemos " << n << ((n!=1) ? "elementos" : "elemento") << endl;

Mostrar los varlores de un array separados con comas, en seis columnas:

    int v[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24 };
    int N = 24;
    for(int i = 0; i < N; i++)
        cout << v[i] << ((i%6==5 || i==N-1) ? "\n" : ",");

Comentarios de los usuarios (3)

Carlos
2011-07-09 22:03:46

Buenas! en mi ordenador al intentar compilar los 2 ultimos ejemplos del ?: me sale el siguiente error:

error: overloaded function with no contextual type information

¿Alguna idea de por qué?

Alejandro
2012-05-17 12:47:45

A mi me pasa lo mismo, creo que la clave es que

endl
y
 ", "
son cosas distintas

me ha compilado y funcionando bien con

for(int i=0;i<N;i++){
      cout << V[i];
     (i%6==5 || i==N-1)? (cout<<endl) : (cout<<", ");
}

Pero antes de eso probé otras cosas como cambiar "endl" por "\n" y la salida fue 1 cuando debía ser cambio de línea y "0" cuando debía de salir ", "

y si pones

 cout << V[i]<< ((i%6==5 || i==N-1)? (cout<<endl) : (cout<<", "));

Hace el cambio de linea pero en lugar de ", " pone un número hexadecimal

Salvador Pozo
2012-05-17 17:19:10

Ya está solucionado, unos paréntesis y, efectivamente, endl no es del mismo tipo que ",", de modo que he cambiado el método de cout por un "\n".