Operadores a nivel de bits (lenguaje C).

Iniciado por NOB2014, 16 Marzo 2014, 02:48 AM

0 Miembros y 1 Visitante están viendo este tema.

NOB2014

Hola a todos.
Estoy estudiando "Operadores a nivel de bits" y no sólo deseo aprender la sintaxis sino también interpretar lo que hace cada línea de código.-

Lenguaje: "C"

Problema: (dudas) Expuesta en el código. 
                                                                                 
Error: Ninguno.

Otras Observaciones: Ninguna.

Código:


# include <stdio.h>

void despriegaBits(unsigned valor);

int main(void){
unsigned x; //No entiendo esta declaracion de variable, cual es el tipo?
printf("\n\n Introduzca un entero sin signo....:");
scanf("%u", &x);

despriegaBits(x);

return 0;
}

void despriegaBits(unsigned valor){
unsigned c; //No entiendo esta declaracion de variable, cual es el tipo?

unsigned despliegaMascara = 1 << 31; //Esta sentencia como se llama?, pareceria una funcion, pero no
                                             //tiene parentesis, me desconcierta, y lo mas importante, como funciona?, que hace?.

printf("\n %10u = ", valor);

for(c = 1; c <= 32; c++){
putchar(valor & despliegaMascara ? '1' : '0');
valor <<= 1;

if(c % 8 == 0){
putchar(' ');
}
}
putchar('\n');
}


Desde ya muchas gracias por la ayuda que puedan brindarnos.-
Saludos.
Daniel
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

engel lex

"unsigned" es una forma corta de "unsigned int" que es entero sin signo (solo positivos)

despliegaMascara = 1 << 31;

el >> y << sirven para mover un bit a la derecha o izquierda...

se usan igual que los operadores aritmeticos (a = 1 + 2)

se toma 1 en binario (que es igual 1) y se mueve 31 veces a la izquierda


1
10
100
1000
------
100000000000000000000000000000000

el valor en entero de esa variable no es importante en este caso... ya que se usará para una comparación en binario...

alguna otra duda?


por cierto! te llevas una buena cantidad de puntos por hacer un post bien explicado y con platilla y todo XD
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

NOB2014

Hola angelx.
Sí, me quedan dudas sobre tu explicación, no porque este mal hecha( todo lo contrario) solo que siempre tardo en que me caiga la ficha, cuando esto ocurra los volveré a consultar.-

Saludos.
Daniel
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

engel lex

ok ;) no hoy problema... de toda formas dejo unos datos más



paso a paso las operaciones serían
a = 5 << 6;

      101
     1010
    10100
   101000
  1010000
10100000
101000000

resultado: a -> B101000000 (B por binario)
---------------------------------------
a = 84 >> 3;
1010100
101010
  10101
   1010

resultado: a->B1010
en este segundo caso los bits mas bajos simplemente desaparecen
---------------------------------------
a = 5;
a =<< 3; (esta expresion es similar a decir a = a<<3)
   101
  1010
10100
resultado: a->B10100
---------------------------------------
a = 5 & 3
esto es un and lógico normal
101
011
___
001
resultado: a->1
---------------------------------------
a = 86 | 34
esto es un or lógico inclusivo
1010110
100010
_______
1110110
resultado: a->B1110110
---------------------------------------
a = 86 ^ 34
esto es un or lógico exclusivo (o xor)
1010110
100010
_______
1110100
resultado: a->B1110100




ahí tienes operadores binarios y su uso :P
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

rir3760

Un problema con ese programa es asumir que el tipo unsigned int esta constituido por 32 bits (si son mas el resultado es incorrecto, si son menos el programa reventara por el desplazamiento).

Una mejor aproximación consiste en utilizar el operador sizeof para obtener el numero de bytes y la macro CHAR_BIT para el numero de bits:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

void imprimir(unsigned num);

int main(void)
{
   unsigned num;
   
   printf("Introduce un entero no negativo: ");
   fflush(stdout);
   if (scanf("%u", &num) != 1)
      return EXIT_FAILURE;
   
   imprimir(num);
   
   return EXIT_SUCCESS;
}

void imprimir(unsigned num)
{
   unsigned msb = 1U << sizeof(unsigned) * CHAR_BIT - 1;
   size_t i;
   size_t j;
   
   for (i = 0; i < sizeof(unsigned); i++){
      for (j = 0; j < CHAR_BIT; j++){
         putchar(num & msb ? '1' : '0');
         msb >>= 1;
      }
     
      putchar(' ');
   }
   putchar('\n');
}


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

ivancea96

Si son menos, el programa no revienta, simplemente se pierden los bits :o

Enviado desde mi ST21i mediante Tapatalk

rir3760

Cita de: ivancea96 en 16 Marzo 2014, 15:54 PM
Cita de: rir3760 en 16 Marzo 2014, 15:10 PMUn problema con ese programa es asumir que el tipo unsigned int esta constituido por 32 bits (si son mas el resultado es incorrecto, si son menos el programa reventara por el desplazamiento).

Si son menos, el programa no revienta, simplemente se pierden los bits
No (por el desplazamiento). Para explicarlo mejor considerando que el numero de iteraciones y el desplazamiento esta dado por "magic numbers":
unsigned despliegaMascara = 1 << 31;

/* ... */

for(c = 1; c <= 32; c++) ...


Si el numero de bits del tipo unsigned int es:
A) Mayor (por ejemplo 64) entonces solo se procesa una parte de los bits.
B) Menor (por ejemplo 16) entonces el desplazamiento "1 << 31" causara que el programa reviente ya que el segundo operando debe ser mayor que cero y menor que el numero de bits del objeto.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Yoel Alejandro

#7
¿Qué se quiere decir exactamente con que el programa "revienta"? ¿Fuga de memoria, terminación anormal?

Hice una prueba, tomé el unsigned 1 y fui desplazando sus bits a la izquierda e imprimiendo el resultado por bits (con las mismas funciones dadas aportadas en el tema), para observar lo que ocurre luego del desplazamiento número 31.

Para mayor seguridad mandé imprimir antes la cantidad de bits de la representación de enteros en mi máquina y verificar que son 32. El resultado del programa:

En esta maquina los enteros ocupan 32 bits
29: 00100000 00000000 00000000 00000000
30: 01000000 00000000 00000000 00000000
31: 10000000 00000000 00000000 00000000
32: 00000000 00000000 00000000 00000000
33: 00000000 00000000 00000000 00000000

Se aprecia que en los desplazamientos 32 en adelante simplemente se pierde el bit y el número queda compuesto por ceros, pero la consola no me indica terminacióna anormal. Consulté el estado de salida del proceso (echo $?, para bash) y fue 0 (normal).

¿Qué me dicen ustedes?

====================
(EDITO) Ya comprendí el dilema, creo que no estamos hablando de lo mismo. La instrucción "num << 31" tendrá un comportamiento indefinido (pero no un error fatal) si el operando a la derecha es mayor que la longitud en bits del operando a la izquierda. Lo que yo hice fue diferente, ejecutar "num << 1" reiterativamente más de 31 veces.
====================

Código (cpp) [Seleccionar]

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

void imprimir(unsigned num);

int main( ) {

   unsigned num = 1;
   int i;

   printf("En esta maquina los enteros ocupan %d bits\n",
          sizeof(unsigned) * CHAR_BIT);

   for (i = 0; i < 34; num <<= 1, i++ )
      if ( i > 28 ) {
         printf( "%d: ", i );
         imprimir( (unsigned) num );
      }

   return 0;
}

void imprimir(unsigned num)
{
   unsigned msb = 1U << sizeof(unsigned) * CHAR_BIT - 1;
   size_t i;
   size_t j;

   for (i = 0; i < sizeof(unsigned); i++) {
      for (j = 0; j < CHAR_BIT; j++) {
         putchar(num & msb ? '1' : '0');
         msb >>= 1;
      }
      putchar(' ');
   }
   putchar('\n');
}
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)

NOB2014

Hola a todos.
Gracias a , ivancea96,Rir3760,yoel_alejandro por la ayuda, me interesa el código de estos último dos que luego de debelar las dudas que expongo a continuación voy a correrlos y estudiarlos.-

unsigned despliegaMascara = 1 << 31;
engelx ¿me podrías decir cuál es el valor final de despliegaMascara?, no logro mostrarlo con un printf y mil disculpas por la ignoracia al suponer que podía ser una función.-

putchar(valor & despliegaMascara ? '1' : '0');
En esta línea valor en cada iteración se mueve un bits a la izquierda ¿ con despliegaMascara no debería pasar lo mismo ?.-

Demás esta aclarar que la ayuda de cualquiera es bienvenida.-

Saludos.
Daniel 
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

engel lex

Citarengelx ¿me podrías decir cuál es el valor final de despliegaMascara?
teoricamente el valor es 2147483648 pero eso no es lo importante, solo importa como binario...

despliegue mascara vale en binario
100000000000000000000000000000000


CitarEn esta línea valor en cada iteración se mueve un bits a la izquierda ¿ con despliegaMascara no debería pasar lo mismo ?

no despliegaMascara es simplemente para comprobar si hay un 1 en el bit más a la izquierda
por ejemplo con el numero 5


despliegueMascara = 100000000000000000000000000000000
5 en binario = 101
c= 1
100000000000000000000000000000000
000000000000000000000000000000101
recordando que esto es un and esto igual a 0...
asi que simplemente colocaré varios pasos

c= 2
100000000000000000000000000000000
000000000000000000000000000001010 = 0

c= 3
100000000000000000000000000000000
000000000000000000000000000010100 = 0
.........
c= 29
100000000000000000000000000000000
010100000000000000000000000000000 = 0

c= 30
100000000000000000000000000000000
101000000000000000000000000000000 !=0 esto imprime un 1

c= 31
100000000000000000000000000000000
010000000000000000000000000000000 = 0

c= 32
100000000000000000000000000000000
100000000000000000000000000000000 !=0 esto imprime un 1


sabras que "?" es un if resumido

Código (cpp) [Seleccionar]
putchar(valor & despliegaMascara ? '1' : '0');

es lo mismo que
Código (cpp) [Seleccionar]

if(valor & despliegaMascara){
    putchar('1');
}else{
    putchar('0');
}
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.