Si queremos imprimir en binario tenemos que escanear cada uno de sus bits e imprimir un '1' ó un '0' según el caso. Pongamos el ejemplo del numero:
num = 1000 1001
Entonces comenzamos con la máscara mask = 1000 0000 (0x80 en hexadecimal). Hacemos el AND binario entre el número y la máscara. Observa bien que la máscara tendrá un único bit en 1, los demás en 0. Si el AND binario da como resultado distinto de cero es porque el número original posee un '1' en la misma posición de la máscara. Así que el bit más significativo del número es '1':
num & mask = 1000 1001 & 1000 0000 = 1000 0000
Ahora seguimos recorriendo el número de izquierda a derecha, para ellos usamos la máscara mask = 0100 0000 (0x40 en hexadecimal). El resultado será '0', porque el número posee un bit '0' en la misma posición donde la máscara tiene su único 'bit 1':
num & mask = 1000 1001 & 0100 0010 = 0000 0000
Y así ya conoces el valor de los dos bits más significativos de num. Siguiendo con las máscaras 0010 0000, 0001 0000, etc., conocerás los demás bits.
Observa que las máscaras sucesivas se obtienen fácilmente empezando con 1000 0000 y rotando a la derecha tantas veces como uno menos que la cantidad total de dígitos binarios que posea el número.
Así, un programa para imprimir en binario un número char sería, donde por sencillez sustituyo el operador ternario "?:" por un "if" estándar:
Código
void imprimir(unsigned char num) { unsigned char mask = 0x80; /* la mascara */ size_t i; for (i = 0; i < sizeof(char) * CHAR_BIT; i++) { if ( num & mask ) putchar('1'); else putchar('0'); mask >>= 1; } }
=============
OBSERVACIONES: 1. Una forma de inicializar la máscara hubiera sido mask = 0x01 << 7, o sea agarrar el 0x01 y rodar el '1' a la izquierda 7 veces. O más consistentemente, mask = 1 << sizeof(char) * CHAR_BIT - 1. Digo que la segunda forma es más consistente, porque se puede cambiar fácilmente el tipo char por short int, o por int donde el tamaño del número en bits es determinado automáticamente por el compilador en lugar de hacerlo nosotros manualmente.
2. El importante el tipo de la máscara como "unsigned". Pues según las especificaciones para enteros signados negativos el comportamiento de la operación ">>" queda indeterminado. Los bits desplazados en la parte izquierda del número pudieran ser rellenados por '1', o por '0' dependiendo del sistema.