No puedes hacer esto, hasta donde yo sé, usando printf. Obviamente, podrías escribir un método de ayuda para lograr esto, pero eso no suena como la dirección que quieres seguir.
Ian P
No hay un formato predefinido para eso. Necesita transformarlo usted mismo en una cadena y luego imprimir la cadena.
No como parte de la Biblioteca ANSI Standard C: si está escribiendo código portátil, el método más seguro es rodar el suyo.
tomlogic
Una solución estándar y genérica (para cualquier tipo integral de cualquier longitud) de la conversión a cadena binaria en C ++: stackoverflow.com/a/31660310/1814353
Necesitas todas las citas extra desafortunadamente. Este enfoque tiene los riesgos de eficiencia de las macros (no pase una función como argumento BYTE_TO_BINARY) pero evita los problemas de memoria y las múltiples invocaciones de strcat en algunas de las otras propuestas aquí.
Y tiene la ventaja de ser invocable varias veces en una printfque los que tienen staticbuffers no pueden.
Patrick Schlüter
44
Me he tomado la libertad de cambiar el %da %c, porque debería ser aún más rápido ( %dtiene que realizar la conversión digit-> char, mientras que %csimplemente genera el argumento
Tenga en cuenta que este enfoque no es amistoso con la pila. Suponiendo que el sistema inttenga 32 bits, la impresión de un solo valor de 32 bits requerirá espacio para los valores de 32 * 4 bytes; total de 128 bytes. Lo cual, dependiendo del tamaño de la pila, puede o no ser un problema.
user694733
1
es importante agregar paréntesis alrededor del byte en la macro o podría tener problemas al enviar una operación BYTE_TO_BINARY (a | b) -> a | b & 0x01! = (a | b) & 0x01
Ivan Hoffmann
203
Imprimir binario para cualquier tipo de datos
//assumes little endianvoid printBits(size_tconst size,voidconst*const ptr){unsignedchar*b =(unsignedchar*) ptr;unsignedchar byte;int i, j;for(i=size-1;i>=0;i--){for(j=7;j>=0;j--){
byte =(b[i]>> j)&1;
printf("%u", byte);}}
puts("");}
prueba
int main(int argv,char* argc[]){int i =23;uint ui = UINT_MAX;float f =23.45f;
printBits(sizeof(i),&i);
printBits(sizeof(ui),&ui);
printBits(sizeof(f),&f);return0;}
¿Podría alguien explicar la lógica detrás de este código?
jII
2
Tome cada byte en ptr(bucle externo); entonces para cada bit el byte actual (bucle interno), enmascare el byte por el bit actual ( 1 << j). Desplace esa derecha dando como resultado un byte que contenga 0 ( 0000 0000b) o 1 ( 0000 0001b). Imprima el byte resultante printf con formato %u. HTH.
nielsbot
1
@ ZX9 Observe que el código sugerido se utiliza >con size_ty no el >=de su comentario para determinar cuándo finalizar el ciclo.
chux
3
@ ZX9 Sigue siendo un comentario original útil suyo, ya que los codificadores deben tener cuidado al considerar el uso de mayúsculas >y minúsculas y >=con tipos sin signo. 0es un caso de borde sin signo y ocurre comúnmente, a diferencia de las matemáticas con signo menos comunes INT_MAX/INT_MIN.
chux
151
Aquí hay un truco rápido para demostrar técnicas para hacer lo que quieres.
#include<stdio.h>/* printf */#include<string.h>/* strcat */#include<stdlib.h>/* strtol */constchar*byte_to_binary
(int x
){staticchar b[9];
b[0]='\0';int z;for(z =128; z >0; z >>=1){
strcat(b,((x & z)== z)?"1":"0");}return b;}int main
(void){{/* binary string to int */char*tmp;char*b ="0101";
printf("%d\n", strtol(b,&tmp,2));}{/* byte to binary string */
printf("%s\n", byte_to_binary(5));}return0;}
Esto es ciertamente menos "extraño" que escribir de forma personalizada una sobrecarga de escape para printf. También es fácil de entender para un desarrollador nuevo en el código.
Furious Coder
43
Algunos cambios: strcates un método ineficiente de agregar un único carácter a la cadena en cada pasada del bucle. En su lugar, agregue char *p = b;ay reemplace el bucle interno con *p++ = (x & z) ? '1' : '0'. zdebería comenzar en 128 (2 ^ 7) en lugar de 256 (2 ^ 8). Considere actualizar para llevar un puntero al búfer para usar (por seguridad de subprocesos), similar a inet_ntoa().
tomlogic
3
@EvilTeach: ¡Usted mismo está utilizando un operador ternario como parámetro para strcat()! Estoy de acuerdo en que strcatprobablemente sea más fácil de entender que el incremento posterior de un puntero desreferenciado para la tarea, pero incluso los principiantes necesitan saber cómo usar correctamente la biblioteca estándar. Tal vez usar una matriz indexada para la asignación hubiera sido una buena demostración (y realmente funcionará, ya bque no se restablece a todos ceros cada vez que se llama a la función).
tomlogic
3
Aleatorio: el carácter binario del búfer es estático y se borra a todos los ceros en la asignación. Esto solo lo borrará la primera vez que se ejecute, y después de eso no se borrará, sino que usará el último valor.
markwatson
8
Además, este debe documentar que el resultado anterior no será válido después de llamar a la función de nuevo, por lo que las personas que llaman no debe tratar de utilizar de esta manera: printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4)).
Paŭlo Ebermann
84
No hay un especificador de conversión binaria en glibc normalmente.
Es posible agregar tipos de conversión personalizados a la familia de funciones printf () en glibc. Ver register_printf_function para más detalles. Puede agregar una conversión% b personalizada para su propio uso, si simplifica el código de la aplicación para tenerla disponible.
Aquí hay un ejemplo de cómo implementar formatos de impresión personalizados en glibc.
Siempre he escrito mi propio v [snf] printf () para los casos limitados en los que quería diferentes radixs: me alegro de haber examinado esto.
Jamie
3
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]Hay una nueva función para hacer lo mismo, sin embargo: register_printf_specifier(). Puede encontrar un ejemplo del nuevo uso aquí: codereview.stackexchange.com/q/219994/200418
Cacahuete Frito
47
Puede usar una mesa pequeña para mejorar la velocidad 1 . Técnicas similares son útiles en el mundo incrustado, por ejemplo, para invertir un byte:
Imprima el bit menos significativo y muévalo a la derecha. Hacer esto hasta que el entero se convierta en cero imprime la representación binaria sin ceros a la izquierda pero en orden inverso. Usando la recursividad, el orden se puede corregir con bastante facilidad.
Para mí, esta es una de las soluciones más limpias para el problema. Si le gusta el 0bprefijo y un nuevo carácter de línea final, sugiero ajustar la función.
error: muy pocos argumentos para llamar a la función, esperado 2, tienen 1 putc ((número y 1)? '1': '0');
Koray Tugay
@KorayTugay Gracias por señalar eso. Corregí la llamada a la función y agregué una demostración.
danijar
66
también debe usar un número int sin signo, porque cuando el número dado es negativo, la función ingresa en una llamada recursiva interminable.
Puffy
Enfoque más eficiente, ya que en ASCII, '0' + 1 = '1':putc('0'+(number&1), stdout);
Roger Dueck
22
Sobre la base de la respuesta de @William Whyte, este es un macro que proporciona int8, 16, 32y 64versiones, la reutilización de la INT8macro a la repetición evitar.
Sí, se puede hacer eso. Pero es realmente un mal diseño. Incluso si no tiene subprocesos o reentrada, la persona que llama debe ser consciente de que el búfer estático se está reutilizando y que cosas como las char *a = binary_fmt(x), *b = binary_fmt(y);que no funcionan como se esperaba. Obligar a la persona que llama a pasar un búfer hace explícito el requisito de almacenamiento; la persona que llama es, por supuesto, libre de usar un búfer estático si realmente lo desea, y luego la reutilización del mismo búfer se vuelve explícita. También tenga en cuenta que, en las ABI modernas de PIC, los buffers estáticos generalmente cuestan más código para acceder que los buffers en la pila.
R .. GitHub DEJA DE AYUDAR AL HIELO
8
Eso sigue siendo un mal diseño. Requiere un paso de copia adicional en esos casos, y no es menos costoso que hacer que la persona que llama proporcione el búfer incluso en los casos en que no se requiera la copia. Usar almacenamiento estático es solo una mala expresión.
R .. GitHub DEJA DE AYUDAR AL HIELO
3
Tener que contaminar el espacio de nombres de la tabla de símbolos de preprocesador o variable con un nombre adicional innecesario que debe usarse para dimensionar adecuadamente el almacenamiento que debe asignar cada persona que llama, y obliga a cada persona que llama a conocer este valor y asignar la cantidad necesaria de almacenamiento, es un mal diseño cuando la solución de almacenamiento local de función más simple será suficiente para la mayoría de los intentos y propósitos, y cuando una simple llamada strdup () cubre el 99% del resto de los usos.
Greg A. Woods,
55
Aquí vamos a tener que estar en desacuerdo. No puedo ver cómo agregar un símbolo de preprocesador discreto se acerca a la nocividad de limitar severamente los casos de uso, haciendo que la interfaz sea propensa a errores, reservando almacenamiento permanente durante la duración del programa por un valor temporal y generando peor código en la mayoría plataformas modernas
R .. GitHub DEJA DE AYUDAR A HIELO
55
No abogo por la micro-optimización sin razón (es decir, mediciones). Pero sí creo que vale la pena mencionar el rendimiento, incluso si está en la escala de micro ganancia, cuando se trata de una bonificación junto con un diseño fundamentalmente superior.
Más claro si usa '1'y en '0'lugar de 49y 48en su ternario. Además, bdebe tener 9 caracteres de longitud para que el último carácter pueda seguir siendo un terminador nulo.
tomlogic
Además, B debe inicializarse cada vez.
EvilTeach
2
No si cambia alguna: 1. Agregar espacio para un cero final: static char b[9] = {0}2. Declaración movimiento fuera del bucle: int z,y;3. Añadir el cero final: b[y] = 0. De esta manera no se necesita reinitalización.
Kobor42
1
Buena solución Aunque cambiaría algunas cosas. Es decir, retroceder en la cadena para que la entrada de cualquier tamaño se pueda manejar correctamente.
Kobor42
Todos esos 8s deben ser reemplazados por CHAR_BIT.
Funciona para cualquier tipo de tamaño y para entradas firmadas y sin firmar. El '& 1' es necesario para manejar entradas firmadas ya que el cambio puede hacer la extensión de la señal.
Hay muchas formas de hacer esto. Aquí hay uno súper simple para imprimir 32 bits o n bits desde un tipo de 32 bits con signo o sin signo (sin poner un negativo si está firmado, solo imprime los bits reales) y sin retorno de carro. Tenga en cuenta que i disminuye antes del cambio de bit:
¿Qué hay de devolver una cadena con los bits para almacenar o imprimir más tarde? Puede asignar la memoria y devolverla, y el usuario tiene que liberarla, o bien puede devolver una cadena estática, pero se bloqueará si se vuelve a llamar o por otro hilo. Ambos métodos mostrados:
// memory allocated string returned which needs to be freedchar*pstr = int_to_bitstring_alloc(0x97e50ae6,17);
printf("bits = 0b%s\n", pstr);
free(pstr);// no free needed but you need to copy the string to save it somewhere elsechar*pstr2 = int_to_bitstring_static(0x97e50ae6,17);
printf("bits = 0b%s\n", pstr2);
@JanusTroelsen, o mucho más limpio, más pequeño, mantenible:char *buffer = malloc(sizeof(*buffer) * 50);
Shahbaz
¿Por qué "% B" sería diferente a "% b" a este respecto? Las respuestas anteriores decían cosas como "No hay una función de formato en la biblioteca estándar C para generar binarios como ese". y " Algunos tiempos de ejecución admiten"% b "aunque eso no es un estándar". .
Peter Mortensen
8
Algunos tiempos de ejecución admiten "% b", aunque eso no es un estándar.
Esto es en realidad una propiedad de la biblioteca de tiempo de ejecución C, no del compilador.
cjm
7
Este código debe manejar sus necesidades de hasta 64 bits. Creé 2 funciones pBin y pBinFill. Ambos hacen lo mismo, pero pBinFill llena los espacios iniciales con el fillChar. La función de prueba genera algunos datos de prueba, luego los imprime utilizando la función.
char* pBinFill(longint x,char*so,char fillChar);// version with fillchar* pBin(longint x,char*so);// version without fill#define kDisplayWidth 64char* pBin(longint x,char*so){char s[kDisplayWidth+1];int i=kDisplayWidth;
s[i--]=0x00;// terminate stringdo{// fill in array from right to left
s[i--]=(x &1)?'1':'0';// determine bit
x>>=1;// shift right 1 bit}while( x >0);
i++;// point to last valid character
sprintf(so,"%s",s+i);// stick it in the temp string stringreturn so;}
char* pBinFill(longint x,char*so,char fillChar){// fill in array from right to leftchar s[kDisplayWidth+1];int i=kDisplayWidth;
s[i--]=0x00;// terminate stringdo{// fill in array from right to left
s[i--]=(x &1)?'1':'0';
x>>=1;// shift right 1 bit}while( x >0);while(i>=0) s[i--]=fillChar;// fill with fillChar
sprintf(so,"%s",s);return so;}
void test(){char so[kDisplayWidth+1];// working buffer for pBinlongint val=1;do{
printf("%ld =\t\t%#lx =\t\t0b%s\n",val,val,pBinFill(val,so,'0'));
val*=11;// generate test data}while(val <100000000);}Output:00000001=0x000001=0b0000000000000000000000000000000100000011=0x00000b=0b0000000000000000000000000000101100000121=0x000079=0b0000000000000000000000000111100100001331=0x000533=0b0000000000000000000001010011001100014641=0x003931=0b0000000000000000001110010011000100161051=0x02751b=0b0000000000000010011101010001101101771561=0x1b0829=0b0000000000011011000010000010100119487171=0x12959c3=0b00000001001010010101100111000011
"#define width 64" entra en conflicto con stream.h desde log4cxx. Por favor, use nombres de definición aleatorios convencionales :)
kagali-san
55
@mhambra: ¡deberías decirle a log4cxx que no use un nombre tan genérico como en su widthlugar!
u0b34a0f6ae
7
¿Hay un convertidor printf para imprimir en formato binario?
La printf()familia solo puede imprimir en base 8, 10 y 16 utilizando directamente los especificadores estándar. Sugiero crear una función que convierta el número en una cadena según las necesidades particulares del código.
Para imprimir en cualquier base [2-36]
Todas las demás respuestas hasta ahora tienen al menos una de estas limitaciones.
Use memoria estática para el búfer de retorno. Esto limita el número de veces que la función puede usarse como argumento para printf().
Asigne memoria que requiere el código de llamada para liberar punteros.
Requerir que el código de llamada proporcione explícitamente un búfer adecuado.
Llamar printf()directamente Esto obliga a una nueva función para la que fprintf(), sprintf(), vsprintf(), etc.
Use un rango entero reducido.
Lo siguiente no tiene ninguna de las limitaciones anteriores . Requiere C99 o posterior y uso de "%s". Utiliza un literal compuesto para proporcionar el espacio del búfer. No tiene problemas con múltiples llamadas en a printf().
#include<assert.h>#include<limits.h>#define TO_BASE_N (sizeof(unsigned)*CHAR_BIT +1)// v. compound literal .v#define TO_BASE(x, b) my_to_base((char[TO_BASE_N]){""},(x),(b))// Tailor the details of the conversion function as needed// This one does not display unneeded leading zeros// Use return value, not `buf`char*my_to_base(char*buf,unsigned i,int base){
assert(base >=2&& base <=36);char*s =&buf[TO_BASE_N -1];*s ='\0';do{
s--;*s ="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % base];
i /= base;}while(i);// Could employ memmove here to move the used buffer to the beginningreturn s;}#include<stdio.h>int main(void){int ip1 =0x01020304;int ip2 =0x05060708;
printf("%s %s\n", TO_BASE(ip1,16), TO_BASE(ip2,16));
printf("%s %s\n", TO_BASE(ip1,2), TO_BASE(ip2,2));
puts(TO_BASE(ip1,8));
puts(TO_BASE(ip1,36));return0;}
Esto es muy útil ¿Sabes cómo usarlo en C ++? Cuando compilo, genera un error "Código de gravedad Descripción Archivo de proyecto Error de estado de supresión de línea C4576 un tipo entre paréntesis seguido de una lista de inicialización es una sintaxis de conversión de tipo explícito no estándar hola C: \ my_projects \ hello \ hello \ main.cpp 39 "
Solo aprendiz el
1
@Justalearner Esto genera un C ++ porque si usa un literal compuesto de característica C que no es parte de C ++. Quizás publique su implementación de C ++ que intente hacer lo mismo, incluso si está incompleta, estoy seguro de que obtendrá ayuda, siempre que muestre su intento primero.
chux - Restablecer Monica
6
Tal vez un poco OT, pero si necesita esto solo para depurar para comprender o volver sobre algunas operaciones binarias que está haciendo, puede echar un vistazo a wcalc (una calculadora de consola simple). Con las opciones -b obtienes salida binaria.
También hay algunas otras opciones en este frente ... ruby -e 'printf("%b\n", 0xabc)', dcseguidas de 2oseguidas de 0x123p, y así sucesivamente.
lindes
6
No hay una función de formateo en la biblioteca estándar de C para generar binarios como ese. Todas las operaciones de formato que admite la familia printf son para texto legible por humanos.
Si desea utilizar la memoria dinámica (a través std::string), también podría deshacerse de la staticmatriz. La forma más sencilla sería simplemente soltar el staticcalificador y hacer bque la función sea local.
Shahbaz
((x>>z) & 0x01) + '0'es suficiente.
Jason C
4
Imprima bits de cualquier tipo usando menos código y recursos
Este enfoque tiene como atributos:
Funciona con variables y literales.
No itera todos los bits cuando no es necesario.
Llame a printf solo cuando complete un byte (no innecesariamente para todos los bits).
Funciona para cualquier tipo.
Funciona con poca y gran endianness (usa GCC #defines para verificar).
Utiliza typeof () que no es estándar C pero está ampliamente definido.
He usado otro enfoque ( bitprint.h ) para llenar una tabla con todos los bytes (como cadenas de bits) e imprimirlos en función del byte de entrada / índice. Vale la pena echarle un vistazo.
void
print_binary(unsignedint n){unsignedint mask =0;/* this grotesque hack creates a bit pattern 1000... *//* regardless of the size of an unsigned int */
mask =~mask ^(~mask >>1);for(; mask !=0; mask >>=1){
putchar((n & mask)?'1':'0');}}
O agregue 0 o 1 al valor de carácter de '0';) No se necesita ternario.
Búho
3
Me gustó el código de paniq, el buffer estático es una buena idea. Sin embargo, falla si desea múltiples formatos binarios en un solo printf () porque siempre devuelve el mismo puntero y sobrescribe la matriz.
Aquí hay un menú desplegable de estilo C que gira el puntero en un búfer dividido.
char*
format_binary(unsignedint x){#define MAXLEN 8// width of output format#define MAXCNT 4// count per printf statementstaticchar fmtbuf[(MAXLEN+1)*MAXCNT];staticint count =0;char*b;
count = count % MAXCNT +1;
b =&fmtbuf[(MAXLEN+1)*count];
b[MAXLEN]='\0';for(int z =0; z < MAXLEN; z++){ b[MAXLEN-1-z]=((x>>z)&0x1)?'1':'0';}return b;}
Una vez que countalcanza MAXCNT - 1, el siguiente incremento de countlo haría en MAXCNTlugar de cero, lo que provocará un acceso fuera de los límites de la matriz. Deberías haberlo hecho count = (count + 1) % MAXCNT.
Shahbaz
1
Por cierto, esto sería una sorpresa más tarde para un desarrollador que usa MAXCNT + 1llamadas a esta función de una sola vez printf. En general, si desea dar la opción para más de 1 cosa, hágalo infinito. Números como 4 solo pueden causar problemas.
Shahbaz
3
No hay forma estándar y portátil.
Algunas implementaciones proporcionan itoa () , pero no va a estar en la mayoría, y tiene una interfaz algo mala. Pero el código está detrás del enlace y debería permitirle implementar su propio formateador con bastante facilidad.
Sobre la base de la sugerencia de @ ideasman42 en su respuesta, esta es una macro que proporciona int8, 16, 32y 64versiones, la reutilización de la INT8macro para evitar la repetición.
/* Convert an int to it's binary representation */char*int2bin(int num,int pad){char*str = malloc(sizeof(char)*(pad+1));if(str){
str[pad]='\0';while(--pad>=0){
str[pad]= num &1?'1':'0';
num >>=1;}}else{return"";}return str;}/* example usage */
printf("The number 5 in binary is %s", int2bin(5,4));/* "The number 5 in binary is 0101" */
Pagar el costo de una mala ubicación perjudicará el rendimiento. Pasar la responsabilidad por la destrucción del búfer a la persona que llama no es amable.
EvilTeach
2
A continuación le mostrará el diseño de la memoria:
Respuestas:
Hacky pero funciona para mí:
Para tipos de múltiples bytes
Necesitas todas las citas extra desafortunadamente. Este enfoque tiene los riesgos de eficiencia de las macros (no pase una función como argumento
BYTE_TO_BINARY) pero evita los problemas de memoria y las múltiples invocaciones de strcat en algunas de las otras propuestas aquí.fuente
printfque los que tienenstaticbuffers no pueden.%da%c, porque debería ser aún más rápido (%dtiene que realizar la conversión digit-> char, mientras que%csimplemente genera el argumentointtenga 32 bits, la impresión de un solo valor de 32 bits requerirá espacio para los valores de 32 * 4 bytes; total de 128 bytes. Lo cual, dependiendo del tamaño de la pila, puede o no ser un problema.Imprimir binario para cualquier tipo de datos
prueba
fuente
size_t i; for (i=size; i-- > 0; )evitarsize_tvs.intno coincidencia.ptr(bucle externo); entonces para cada bit el byte actual (bucle interno), enmascare el byte por el bit actual (1 << j). Desplace esa derecha dando como resultado un byte que contenga 0 (0000 0000b) o 1 (0000 0001b). Imprima el byte resultante printf con formato%u. HTH.>consize_ty no el>=de su comentario para determinar cuándo finalizar el ciclo.>y minúsculas y>=con tipos sin signo.0es un caso de borde sin signo y ocurre comúnmente, a diferencia de las matemáticas con signo menos comunesINT_MAX/INT_MIN.Aquí hay un truco rápido para demostrar técnicas para hacer lo que quieres.
fuente
strcates un método ineficiente de agregar un único carácter a la cadena en cada pasada del bucle. En su lugar, agreguechar *p = b;ay reemplace el bucle interno con*p++ = (x & z) ? '1' : '0'.zdebería comenzar en 128 (2 ^ 7) en lugar de 256 (2 ^ 8). Considere actualizar para llevar un puntero al búfer para usar (por seguridad de subprocesos), similar ainet_ntoa().strcat()! Estoy de acuerdo en questrcatprobablemente sea más fácil de entender que el incremento posterior de un puntero desreferenciado para la tarea, pero incluso los principiantes necesitan saber cómo usar correctamente la biblioteca estándar. Tal vez usar una matriz indexada para la asignación hubiera sido una buena demostración (y realmente funcionará, yabque no se restablece a todos ceros cada vez que se llama a la función).printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4)).No hay un especificador de conversión binaria en glibc normalmente.
Es posible agregar tipos de conversión personalizados a la familia de funciones printf () en glibc. Ver register_printf_function para más detalles. Puede agregar una conversión% b personalizada para su propio uso, si simplifica el código de la aplicación para tenerla disponible.
Aquí hay un ejemplo de cómo implementar formatos de impresión personalizados en glibc.
fuente
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]Hay una nueva función para hacer lo mismo, sin embargo:register_printf_specifier(). Puede encontrar un ejemplo del nuevo uso aquí: codereview.stackexchange.com/q/219994/200418Puede usar una mesa pequeña para mejorar la velocidad 1 . Técnicas similares son útiles en el mundo incrustado, por ejemplo, para invertir un byte:
1 Me refiero principalmente a aplicaciones integradas donde los optimizadores no son tan agresivos y la diferencia de velocidad es visible.
fuente
Imprima el bit menos significativo y muévalo a la derecha. Hacer esto hasta que el entero se convierta en cero imprime la representación binaria sin ceros a la izquierda pero en orden inverso. Usando la recursividad, el orden se puede corregir con bastante facilidad.
Para mí, esta es una de las soluciones más limpias para el problema. Si le gusta el
0bprefijo y un nuevo carácter de línea final, sugiero ajustar la función.Demostración en línea
fuente
putc('0'+(number&1), stdout);Sobre la base de la respuesta de @William Whyte, este es un macro que proporciona
int8,16,32y64versiones, la reutilización de laINT8macro a la repetición evitar.Esto produce:
Para facilitar la lectura, puede agregar un separador, por ejemplo:
fuente
PRINTF_BYTE_TO_BINARY_INT#define para usar opcionalmente.Aquí hay una versión de la función que no sufre problemas de reentrada o límites en el tamaño / tipo del argumento:
Tenga en cuenta que este código funcionaría igual de bien para cualquier base entre 2 y 10 si solo reemplaza los 2 por la base deseada. El uso es:
¿Dónde
xestá cualquier expresión integral?fuente
char *a = binary_fmt(x), *b = binary_fmt(y);que no funcionan como se esperaba. Obligar a la persona que llama a pasar un búfer hace explícito el requisito de almacenamiento; la persona que llama es, por supuesto, libre de usar un búfer estático si realmente lo desea, y luego la reutilización del mismo búfer se vuelve explícita. También tenga en cuenta que, en las ABI modernas de PIC, los buffers estáticos generalmente cuestan más código para acceder que los buffers en la pila.fuente
'1'y en'0'lugar de49y48en su ternario. Además,bdebe tener 9 caracteres de longitud para que el último carácter pueda seguir siendo un terminador nulo.static char b[9] = {0}2. Declaración movimiento fuera del bucle:int z,y;3. Añadir el cero final:b[y] = 0. De esta manera no se necesita reinitalización.8s deben ser reemplazados porCHAR_BIT.Solución rápida y fácil:
Funciona para cualquier tipo de tamaño y para entradas firmadas y sin firmar. El '& 1' es necesario para manejar entradas firmadas ya que el cambio puede hacer la extensión de la señal.
Hay muchas formas de hacer esto. Aquí hay uno súper simple para imprimir 32 bits o n bits desde un tipo de 32 bits con signo o sin signo (sin poner un negativo si está firmado, solo imprime los bits reales) y sin retorno de carro. Tenga en cuenta que i disminuye antes del cambio de bit:
¿Qué hay de devolver una cadena con los bits para almacenar o imprimir más tarde? Puede asignar la memoria y devolverla, y el usuario tiene que liberarla, o bien puede devolver una cadena estática, pero se bloqueará si se vuelve a llamar o por otro hilo. Ambos métodos mostrados:
Llamar con:
fuente
Ninguna de las respuestas publicadas anteriormente es exactamente lo que estaba buscando, así que escribí una. ¡Es súper simple usar% B con el
printf!fuente
char* buffer = (char*) malloc(sizeof(char) * 50);char *buffer = malloc(sizeof(*buffer) * 50);Algunos tiempos de ejecución admiten "% b", aunque eso no es un estándar.
También vea aquí para una discusión interesante:
http://bytes.com/forum/thread591027.html
HTH
fuente
Este código debe manejar sus necesidades de hasta 64 bits. Creé 2 funciones pBin y pBinFill. Ambos hacen lo mismo, pero pBinFill llena los espacios iniciales con el fillChar. La función de prueba genera algunos datos de prueba, luego los imprime utilizando la función.
fuente
widthlugar!La
printf()familia solo puede imprimir en base 8, 10 y 16 utilizando directamente los especificadores estándar. Sugiero crear una función que convierta el número en una cadena según las necesidades particulares del código.Para imprimir en cualquier base [2-36]
Todas las demás respuestas hasta ahora tienen al menos una de estas limitaciones.
Use memoria estática para el búfer de retorno. Esto limita el número de veces que la función puede usarse como argumento para
printf().Asigne memoria que requiere el código de llamada para liberar punteros.
Requerir que el código de llamada proporcione explícitamente un búfer adecuado.
Llamar
printf()directamente Esto obliga a una nueva función para la quefprintf(),sprintf(),vsprintf(), etc.Use un rango entero reducido.
Lo siguiente no tiene ninguna de las limitaciones anteriores . Requiere C99 o posterior y uso de
"%s". Utiliza un literal compuesto para proporcionar el espacio del búfer. No tiene problemas con múltiples llamadas en aprintf().Salida
fuente
Tal vez un poco OT, pero si necesita esto solo para depurar para comprender o volver sobre algunas operaciones binarias que está haciendo, puede echar un vistazo a wcalc (una calculadora de consola simple). Con las opciones -b obtienes salida binaria.
p.ej
fuente
ruby -e 'printf("%b\n", 0xabc)',dcseguidas de2oseguidas de0x123p, y así sucesivamente.No hay una función de formateo en la biblioteca estándar de C para generar binarios como ese. Todas las operaciones de formato que admite la familia printf son para texto legible por humanos.
fuente
La siguiente función recursiva puede ser útil:
fuente
Optimicé la mejor solución para tamaño y C ++, y llegué a esta solución:
fuente
std::string), también podría deshacerse de lastaticmatriz. La forma más sencilla sería simplemente soltar elstaticcalificador y hacerbque la función sea local.((x>>z) & 0x01) + '0'es suficiente.Imprima bits de cualquier tipo usando menos código y recursos
Este enfoque tiene como atributos:
Salida
He usado otro enfoque ( bitprint.h ) para llenar una tabla con todos los bytes (como cadenas de bits) e imprimirlos en función del byte de entrada / índice. Vale la pena echarle un vistazo.
fuente
fuente
Me gustó el código de paniq, el buffer estático es una buena idea. Sin embargo, falla si desea múltiples formatos binarios en un solo printf () porque siempre devuelve el mismo puntero y sobrescribe la matriz.
Aquí hay un menú desplegable de estilo C que gira el puntero en un búfer dividido.
fuente
countalcanzaMAXCNT - 1, el siguiente incremento decountlo haría enMAXCNTlugar de cero, lo que provocará un acceso fuera de los límites de la matriz. Deberías haberlo hechocount = (count + 1) % MAXCNT.MAXCNT + 1llamadas a esta función de una sola vezprintf. En general, si desea dar la opción para más de 1 cosa, hágalo infinito. Números como 4 solo pueden causar problemas.No hay forma estándar y portátil.
Algunas implementaciones proporcionan itoa () , pero no va a estar en la mayoría, y tiene una interfaz algo mala. Pero el código está detrás del enlace y debería permitirle implementar su propio formateador con bastante facilidad.
fuente
Conversión genérica de una declaración de cualquier tipo integral en la representación de cadena binaria usando la biblioteca estándar :
O solo:
std::cout << std::bitset<sizeof(num) * 8>(num);fuente
Mi solución:
fuente
Sobre la base de la sugerencia de @ ideasman42 en su respuesta, esta es una macro que proporciona
int8,16,32y64versiones, la reutilización de laINT8macro para evitar la repetición.Esto produce:
Para facilitar la lectura, puede cambiar:
#define PRINTF_BINARY_SEPARATORa#define PRINTF_BINARY_SEPARATOR ","o#define PRINTF_BINARY_SEPARATOR " "Esto generará:
o
fuente
Utilizar:
Para obtener más información, consulte Cómo imprimir un número binario a través de printf .
fuente
debería funcionar - no probado.
fuente
fuente
A continuación le mostrará el diseño de la memoria:
fuente
Aquí hay una pequeña variación de la solución de paniq que usa plantillas para permitir la impresión de enteros de 32 y 64 bits:
Y se puede usar como:
Aquí está el resultado:
fuente