Post on 23-Jan-2018
MANEJO DE BITS
INTRODUCCIÓN
Una computadora sin software sólo tiene
capacidades para hacer operaciones aritméticas
simples (sumas, restas, multiplicación, etc.)
El software se vale de estas simples operaciones
para crear interfaces como las que vemos en los
modernos sistemas operativos.
Todos los lenguajes, desde los más altos como
“PHP”, hasta los más bajos como “Ensamblador”,
pasan por binario; cada vez que se mueve el ratón
se invocan procesamiento de datos binarios.
INTRODUCCIÓN
Una de las razones por las que C y C++ se han
hecho tan populares es por que el lenguaje ofrece
muchos operadores de manipulación de bits a bajo
nivel.
Los operadores de manipulación de bits (bitwise)
ejecutan operaciones lógicas sobre cada uno de
los bits de los operandos.
Estas operaciones son comparables en eficiencia y
en velocidad a sus equivalentes en lenguaje
ensamblador.
INTRODUCCIÓN
Cada operador de manipulación de bits realiza una
operación lógica, bit a bit, sobre datos internos.
Los operadores de manipulación de bits se aplican
sólo a variables y constantes char, int y long, y no a
datos con punto flotante.
Dado que los números binarios constan de 1’s y 0’s
(bits) estos 1 y 0 se manipulan para producir el
resultado deseado para cada uno de los
operadores.
OPERADORES QUE VEREMOS
"&“
"|“
"^“
"~“
"<<"
">>"
& OPERADOR AND & operador AND de bits (sólo aplicables a variables de
tipo entero)
El operador & (no confundir con el operador lógico &&) es un
operador lógico a nivel de bits.
Compara un par de cadenas de bits por bit; el resultado para
cada comparación es 1 si los bits comparados son ambos 1, y
0 en otro caso.
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
¿CUÁL ES EL RESULTADO DE APLICAR EL
OPERADOR AND?
1 1 0 1 0 1
0 1 1 0 0 1
OPERADOR &
Con este operador & se puede ocultar un conjunto
de bits que no son relevantes en determinada
situación.
Esto constituye una máscara de bits.
Consideremos un pequeño problema y elaborar
una solución:
OPERADOR &
En un ciclo controlado por la variable TAMANO, es
necesario imprimir el valor del contador sólo desde
0 hasta 15, y comenzar después en 0, aún cuando
TAMANO se siga incrementando.
PROCEDIMIENTO DE EJEMPLO ANDvoid operadorAND(void){
/*+++++++++++++++++++++++++++++++++++++++*
*Este procedimiento recibe un par de numeros *
*e imprime el resultado de aplicarles el *
*operador binario & *
*+++++++++++++++++++++++++++++++++++++++*/
int x;
int y;
int res;
cout << "\nEste programa hace uso del operador binario &\n";
cout << "\nIntroduzca un entero: ";
cin >> x;
cout << "\nIntroduzca un segundo entero: ";
cin >> y;
res = x&y;
cout << x <<" " << y << " " << res;
}
USO PRÁCTICO
Tablas de estatus o permisos – se tiene un campo
“permisos” en la base de datos que corresponde a
un campo tipo integer, donde el valor1 = lectura
2 = escritura Cada valor corresponde
4 = ejecución a un bit encendido
8 = otro permiso
Si se lee 3 significa lectura y
escritura.
6 = escritura y ejecución
USO PRÁCTICO
Si se requiere saber si un usuario posee permisos
de escritura, se aplica máscara AND con valor 2.
EJEMPLO DE USO PRÁCTICO
Investiga el valor binario de 1, 2 y 4
Recuerda que 1 significa lectura, 2 significa
escritura y 4 significa ejecución.
Para saber qué permisos tiene un usuario, se
aplica el permiso que uno busca con un operador
AND y el permiso que tiene el usuario.
¿QUÉ PUEDE HACER CADA USUARIO?
Permisos lectura 0 0 0 0 0 0 0 1
Permisos escritura 0 0 0 0 0 0 1 0
Permisos ejecución 0 0 0 0 0 1 0 0
Permisos usuarioA 0 0 0 0 0 1 1 0
Permisos usuarioB 0 0 0 0 0 0 1 1
Permisos usuarioC 0 0 0 0 1 1 1 1
PROCEDIMIENTO DE EJEMPLO MÁSCARA/*+++++++++++++++++++++++++++++++++++++++++++++
* Este procedimiento imprime ciclicamente valores +
* de una variable por debajo de un limite, +
* por medio de una mascara de bits. +
* +++++++++++++++++++++++++++++++++++++++++++*/
#define TAMANO 200
#define LIMITE 15
//LIMITE funciona como una máscara que oculta los bits a la izquierda de
//último 1 a la izquierda.
…
void MASCARA (void){
int i = 0, mascara;
for (i = 0; i < TAMANO; i++)
{
mascara = i & LIMITE;
cout << mascara << "\n";
}
}
07
/09
/201
5
15
Mtl. L
ou
rdes C
ah
uic
h
| OR INCLUSIVO (PALABRA CLAVE BITOR)
Este operador binario tiene un funcionamiento parecido a los anteriores (AND y XOR), salvo que en este caso el resultado es 1 si alguno de ellos está a 1. En caso contrario devuelve 0 (ver ejemplo).
Ejemplo:
int x = 10, y = 20;
int z = x | y; // equivale a:
int z = x bitor y;
Según el enunciado, el operador | aplicado entre los valores 6 y 13 resultaría:
6 == 0000 0110
13 == 0000 1101
------------------
0000 1111 == 15
^ XOR OR EXCLUSIVO (PALABRA CLAVE
XOR)
El funcionamiento de este operador binario es parecido al AND lógico , salvo que en este caso el resultado es 1 si ambos bits son complementarios (uno es 0 y el otro 1). En caso contrario devuelve 0.
Ejemplo:
int x = 10, y = 20;
int z = x ^ y; // equivale a: int z = x xor y;
Según el enunciado, el operador ^ aplicado entre los valores 7 y -2 resultaría:
7 == 0000 0111
-2 == 1111 1110
------------------
1111 1001 == -7
~ COMPLEMENTO A UNO
(PALABRA CLAVE COMPL)
Este operador unitario invierte cada bit del operando; 0
es convertido en 1 y viceversa.
La representación binaria de los complementos a uno de
los decimales 0, 1 y 2 son los que se expresan (para
simplificar los representamos como un octeto):
0 == 0000 0000 ~ 0 == 1111 1111
1 == 0000 0001 ~ 1 == 1111 1110
2 == 0000 0010 ~ 2 == 1111 1101
PROCEDIMIENTO DE EJEMPLOvoid complementoAuno(void){
/*+++++++++++++++++++++++++++++++++++++++++++++
* Este procedimiento cambia un numero sin sigo a +
* su complemento a uno a nivel de bits +
* ++++++++++++++++++++++++++++++++++++++++++*/
short signed cero = 0, uno = 1, dos = 2;
cout << "~0 == " << ~cero << endl;
cout << "~1 == " << ~uno << endl;
cout << "~2 == " << ~dos << endl;
}
<< DESPLAZAMIENTO A IZQUIERDA
Este operador binario realiza un desplazamiento de
bits a la izquierda. El bit más significativo (más a la
izquierda) se pierde, y se le asigna un 0 al menos
significativo (el de la derecha). El operando
derecho indica el número de desplazamientos que
se realizarán.
Recuerde que los desplazamientos no son
rotaciones; los bits que salen por la izquierda se
pierden, los que entran por la derecha se rellenan
con ceros. Este tipo de desplazamientos se
denominan lógicos en contraposición a los cíclicos
o rotacionales.
<< DESPLAZAMIENTO A IZQUIERDA
unsigned long x = 10;
int y = 2;
unsigned long z = x << y;
Según las premisas anteriores, los
desplazamientos izquierda de valor unitario
aplicados sobre los números 0, 1, 2 y -3, producen
los siguientes resultados:
0 == 0000 0000 0 << 1 == 0000 0000 == 0
1 == 0000 0001 1 << 1 == 0000 0010 == 2
2 == 0000 0010 2 << 1 == 0000 0100 == 4
-3 == 1111 1101 -3 << 1 == 1111 1010 == - 6
PROCEDIMIENTO DE EJEMPLO
void desplazamientoAIzquierda(void){
int x = 1;
// Los operadores de bits solo se aplican a variables unsigned
cout << "\nEl tamanio de una variable int es: " << sizeof(int) << endl;
cout << "\nEl valor inicial de x: " << x << endl;
for (unsigned i = 1; i <= 8; i++)
{
unsigned desplazado = x << i;
cout << "\nEl numero: " << desplazado << endl;
}
cout << "\nEl valor final de x: " << x << endl;
}
>> DESPLAZAMIENTO A DERECHA
Igual que el desplazamiento a la izquierda, pero el
desplazamiento de bits es, obviamente, a la
derecha.
Sintaxis
expr-desplazada >> expr-desplazamiento
0 == 0000 0000 0 >> 1 == 0000 0000 == 0
2 == 0000 0010 2 >> 1 == 0000 0001 == 1
-2 == 1111 1110 -2 >> 1 == 1111 1111 == -1
(C++Builder & GNU-C++)
-16 == 1111 0000 -16 >> 2 == 1111 1100 == -4
(C++Builder & GNU-C++)
PROCEDIMIENTO DE EJEMPLOvoid desplazamientoADerecha(void){
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* Este procedimiento hace uso de el operador de desplazamiento *
* hacia la derecha >> *
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int x = 128;
cout << "\nEl tamanio de una variable int es: " << sizeof(int) << endl;
cout << "\nEl valor inicial de x: " << x << endl;
for (unsigned i = 1; i <= 8; i++)
{
unsigned desplazado = x >> i;
cout << "\nEl numero: " << desplazado << endl;
}
cout << "\nEl valor final de x: " << x << endl;
}