Puedo imprimir con printf como un número hexadecimal u octal. ¿Hay una etiqueta de formato para imprimir como base binaria o arbitraria?
Estoy ejecutando gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
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
printf
que los que tienenstatic
buffers no pueden.%d
a%c
, porque debería ser aún más rápido (%d
tiene que realizar la conversión digit-> char, mientras que%c
simplemente genera el argumentoint
tenga 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_t
vs.int
no 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_t
y no el>=
de su comentario para determinar cuándo finalizar el ciclo.>
y minúsculas y>=
con tipos sin signo.0
es 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
strcat
es 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'
.z
deberí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 questrcat
probablemente 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á, yab
que 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
0b
prefijo 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
,32
y64
versiones, la reutilización de laINT8
macro 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
x
está 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 de49
y48
en su ternario. Además,b
debe 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.8
s 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
width
lugar!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)'
,dc
seguidas de2o
seguidas 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 lastatic
matriz. La forma más sencilla sería simplemente soltar elstatic
calificador y hacerb
que 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
count
alcanzaMAXCNT - 1
, el siguiente incremento decount
lo haría enMAXCNT
lugar de cero, lo que provocará un acceso fuera de los límites de la matriz. Deberías haberlo hechocount = (count + 1) % MAXCNT
.MAXCNT + 1
llamadas 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
,32
y64
versiones, la reutilización de laINT8
macro para evitar la repetición.Esto produce:
Para facilitar la lectura, puede cambiar:
#define PRINTF_BINARY_SEPARATOR
a#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