Intenté desplazar a la izquierda un entero de 32 bits por 24:
char *int_to_bin(int num) { int i = 0; static char bin[64]; while (num != 0) { bin[i] = num % 2 + 48; num /= 2; i++; } bin[i] = '\0'; return (bin); } int main() { int number = 255; printf("number: %s\n", int_to_bin(number)); printf("shifted number: %s\n", int_to_bin(number << 24)); return 0; }
SALIDA :
number: 11111111 shifted number: 000000000000000000000000/
y cambié a la izquierda con 23 bits, arroja este resultado:
0000000000000000000000011111111
Bueno, ¿por qué es así y qué pasa con '/' al final del resultado incorrecto?
Dos cosas:
Si el number
tiene el valor 255, entonces el number << 24
tiene el valor numérico 4278190080, que desborda un entero con signo de 32 bits cuyo mayor valor posible es 2147483647. El desbordamiento de entero con signo es un comportamiento indefinido en C, por lo que el resultado podría ser cualquier cosa.
Lo que probablemente sucede en este caso es que el resultado del cambio es negativo. Cuando num
es negativo, num % 2
puede tomar el valor -1
, por lo que almacena el carácter 47 en la cadena, que es /
.
Por lo general, es mejor hacer matemáticas de cambio de bits con tipos unsigned
, donde el desbordamiento está bien definido (se ajusta y los bits simplemente se desplazan hacia la izquierda y desaparecen) y num % 2
solo puede ser 0 o 1. (O escriba num & 1
en su lugar .)
Su rutina int_to_bin
coloca los bits menos significativos al comienzo de la cadena (a la izquierda), por lo que el resultado es al revés de la forma en que la gente suele escribir números (con los bits menos significativos a la derecha). Es posible que desee volver a escribirlo.
Shift funciona bien, simplemente lo imprime desde la dirección incorrecta.
char *int_to_bin(char *buff, int num) { unsigned mask = 1U << (CHAR_BIT * sizeof(num) - 1); char *wrk = buff; for(; mask; mask >>= 1) { *wrk++ = '0' + !!((unsigned)num & mask); } *wrk = 0; return buff; } int main() { char buff[CHAR_BIT * sizeof(int) + 1]; int number = 255; printf("number: %s\n", int_to_bin(buff, number)); printf("shifted number: %s\n", int_to_bin(buff, number << 24)); return 0; }
Desplazar enteros con signo a la izquierda está bien, pero el desplazamiento a la derecha está definido por la implementación. Muchos sistemas utilizan el desplazamiento aritmético a la derecha y el resultado no es el mismo que utilizar el bit a bit:
#include<stdio.h> #include<stdlib.h> char *int_to_bin( unsigned long long int num) { int i = 0; static char bin[65]; while (i != 64) { bin[63-i] = num % 2 + 48; num /= 2; i++; } bin[64] = '\0'; return (bin); } int main() { unsigned long long int number = 255; printf("number 1: %s\n", int_to_bin(number)); printf("number 2: %s\n", int_to_bin(number << 24)); return 0; }