Posso imprimir com printf como um número hexadecimal ou octal. Existe uma etiqueta de formato para imprimir como base binária ou arbitrária?
Estou executando o gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Respostas:
Hacky, mas funciona para mim:
Para tipos de bytes múltiplos
Infelizmente, você precisa de todas as cotações extras. Essa abordagem apresenta os riscos de eficiência das macros (não passe uma função como argumento
BYTE_TO_BINARY
), mas evita os problemas de memória e várias invocações do strcat em algumas das outras propostas aqui.fonte
printf
que os que possuemstatic
buffers não podem.%d
que%c
, porque ele deve ser ainda mais rápido (%d
tem que executar digit-> caractere de conversão, enquanto que%c
simplesmente exibe o argumentoint
32 bits no sistema, a impressão de um valor único de 32 bits exigirá espaço para valores de 32 * 4 bytes; total de 128 bytes. O que, dependendo do tamanho da pilha, pode ou não ser um problema.Binário de impressão para qualquer tipo de dados
teste
fonte
size_t i; for (i=size; i-- > 0; )
para evitarsize_t
vs.int
incompatibilidade.ptr
(loop externo); depois, para cada bit, o byte atual (loop interno), oculte o byte pelo bit atual (1 << j
). Mude para a direita, resultando em um byte contendo 0 (0000 0000b
) ou 1 (0000 0001b
). Imprima o byte resultante printf com o formato%u
. HTH.>
comsize_t
e não com o>=
seu comentário para determinar quando terminar o loop.>
e>=
com tipos não assinados.0
é um caso de borda não assinado e geralmente ocorre, ao contrário da matemática assinada com menos comumINT_MAX/INT_MIN
.Aqui está um truque rápido para demonstrar técnicas para fazer o que você deseja.
fonte
strcat
é um método ineficiente de adicionar um único caractere à string em cada passagem do loop. Em vez disso, adicionechar *p = b;
ae substitua o loop interno por*p++ = (x & z) ? '1' : '0'
.z
deve começar em 128 (2 ^ 7) em vez de 256 (2 ^ 8). Considere atualizar para levar um ponteiro para o buffer a ser usado (para segurança do thread), semelhante ainet_ntoa()
.strcat()
! Concordo questrcat
é provavelmente mais fácil de entender do que o pós-incremento de um ponteiro não referenciado para a tarefa, mas mesmo os iniciantes precisam saber como usar adequadamente a biblioteca padrão. Talvez o uso de uma matriz indexada para atribuição tenha sido uma boa demonstração (e realmente funcionará, poisb
não é redefinido para todos os zeros toda vez que você chama a função).printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4))
.Não há um especificador de conversão binário na glibc normalmente.
É possível adicionar tipos de conversão personalizados à família de funções printf () na glibc. Consulte register_printf_function para obter detalhes. Você pode adicionar uma conversão% b personalizada para seu próprio uso, se simplificar o código do aplicativo para disponibilizá-lo.
Aqui está um exemplo de como implementar um formato printf personalizado na glibc.
fonte
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]
Há uma nova função para fazer o mesmo, no entanto:register_printf_specifier()
. Um exemplo do novo uso pode ser encontrado aqui: codereview.stackexchange.com/q/219994/200418Você pode usar uma pequena mesa para melhorar a velocidade 1 . Técnicas semelhantes são úteis no mundo incorporado, por exemplo, para inverter um byte:
1 Estou me referindo principalmente a aplicativos incorporados nos quais os otimizadores não são tão agressivos e a diferença de velocidade é visível.
fonte
Imprima o bit menos significativo e desloque-o para a direita. Fazer isso até que o número inteiro se torne zero imprime a representação binária sem zeros à esquerda, mas em ordem inversa. Usando a recursão, a ordem pode ser corrigida facilmente.
Para mim, esta é uma das soluções mais limpas para o problema. Se você gosta de
0b
prefixo e um caractere de nova linha à direita, sugiro agrupar a função.Demonstração online
fonte
putc('0'+(number&1), stdout);
Com base na resposta de @William Whyte, esta é uma macro que fornece
int8
,16
,32
e64
versões, reutilizando aINT8
macro à repetição evitar.Isso gera:
Para facilitar a leitura, você pode adicionar um separador, por exemplo:
fonte
PRINTF_BYTE_TO_BINARY_INT#
define para usar opcionalmente.Aqui está uma versão da função que não sofre problemas de reentrada ou limites no tamanho / tipo do argumento:
Observe que esse código funcionaria tão bem para qualquer base entre 2 e 10 se você apenas substituir os 2 pela base desejada. O uso é:
Onde
x
está qualquer expressão integral.fonte
char *a = binary_fmt(x), *b = binary_fmt(y);
não funcionarão conforme o esperado. Forçar o chamador a passar um buffer torna explícito o requisito de armazenamento; é claro que o chamador está livre para usar um buffer estático, se isso for realmente desejado, e a reutilização do mesmo buffer se torna explícita. Observe também que, nas ABIs PIC modernas, os buffers estáticos geralmente custam mais código para acessar do que os buffers na pilha.fonte
'1'
e em'0'
vez de49
e48
em seu ternário. Além disso,b
deve ter 9 caracteres, para que o último caractere possa permanecer um terminador nulo.static char b[9] = {0}
2. declaração movimento fora do circuito:int z,y;
3. Adicione a final zero:b[y] = 0
. Dessa forma, não é necessária reinitalização.8
s devem ser substituídos porCHAR_BIT
.Solução rápida e fácil:
Funciona para qualquer tipo de tamanho e para entradas assinadas e não assinadas. O '& 1' é necessário para manipular entradas registradas, pois a mudança pode significar a extensão.
Existem muitas maneiras de fazer isso. Aqui está um super simples para imprimir 32 bits ou n bits de um tipo assinado ou não assinado de 32 bits (sem colocar negativo se assinado, apenas imprimindo os bits reais) e sem retorno de carro. Observe que i é decrementado antes da mudança de bit:
Que tal retornar uma string com os bits para armazenar ou imprimir posteriormente? Você pode alocar a memória e devolvê-la e o usuário precisa liberá-la; caso contrário, você retorna uma sequência estática, mas ela será derrotada se for chamada novamente ou por outro encadeamento. Ambos os métodos mostrados:
Ligue para:
fonte
Nenhuma das respostas postadas anteriormente é exatamente o que eu estava procurando, então escrevi uma. É super simples de usar% B com o
printf
!fonte
char* buffer = (char*) malloc(sizeof(char) * 50);
char *buffer = malloc(sizeof(*buffer) * 50);
Alguns tempos de execução suportam "% b", embora isso não seja um padrão.
Veja também aqui uma discussão interessante:
http://bytes.com/forum/thread591027.html
HTH
fonte
Este código deve lidar com suas necessidades de até 64 bits. Eu criei 2 funções pBin & pBinFill. Ambos fazem a mesma coisa, mas o pBinFill preenche os espaços iniciais com o fillChar. A função de teste gera alguns dados de teste e os imprime usando a função.
fonte
width
seu!A
printf()
família só pode imprimir nas bases 8, 10 e 16 usando diretamente os especificadores padrão. Sugiro criar uma função que converta o número em uma string de acordo com as necessidades particulares do código.Para imprimir em qualquer base [2-36]
Todas as outras respostas até agora têm pelo menos uma dessas limitações.
Use memória estática para o buffer de retorno. Isso limita o número de vezes que a função pode ser usada como argumento
printf()
.Aloque memória que requer o código de chamada para liberar ponteiros.
Exija que o código de chamada forneça explicitamente um buffer adequado.
Ligue
printf()
diretamente. Isto obriga uma nova função para afprintf()
,sprintf()
,vsprintf()
, etc.Use um intervalo inteiro reduzido.
O seguinte não possui nenhuma das limitações acima . Requer C99 ou posterior e uso de
"%s"
. Ele usa um literal composto para fornecer o espaço no buffer. Não há problemas com várias chamadas em aprintf()
.Resultado
fonte
Talvez um pouco OT, mas se você precisar disso apenas para depuração para entender ou refazer algumas operações binárias que você está fazendo, você pode dar uma olhada no wcalc (uma calculadora simples do console). Com as opções -b, você obtém saída binária.
por exemplo
fonte
ruby -e 'printf("%b\n", 0xabc)'
,dc
seguidas por2o
seguidas0x123p
e assim por diante.Não há nenhuma função de formatação na biblioteca padrão C para gerar binário assim. Todas as operações de formato suportadas pela família printf são direcionadas para texto legível por humanos.
fonte
A seguinte função recursiva pode ser útil:
fonte
Otimizei a melhor solução para tamanho e C ++, e cheguei a esta solução:
fonte
std::string
), também poderá se livrar dastatic
matriz. A maneira mais simples seria simplesmente largar ostatic
qualificador e tornarb
local a função.((x>>z) & 0x01) + '0'
é suficiente.Imprima bits de qualquer tipo usando menos código e recursos
Essa abordagem tem como atributos:
Resultado
Eu usei outra abordagem ( bitprint.h ) para preencher uma tabela com todos os bytes (como cadeias de bits) e imprimi-los com base no byte de entrada / índice. Vale a pena dar uma olhada.
fonte
fonte
Gostei do código do paniq, o buffer estático é uma boa ideia. No entanto, ele falhará se você desejar vários formatos binários em um único printf (), pois sempre retorna o mesmo ponteiro e sobrescreve a matriz.
Aqui está um drop-in no estilo C que gira o ponteiro em um buffer dividido.
fonte
count
atingidoMAXCNT - 1
, o próximo incremento decount
faria emMAXCNT
vez de zero, o que causará um acesso fora dos limites da matriz. Você deveria ter feitocount = (count + 1) % MAXCNT
.MAXCNT + 1
chamadas para essa função em um únicoprintf
. Em geral, se você quiser dar a opção para mais de uma coisa, torne-a infinita. Números como 4 só podem causar problemas.Nenhuma maneira padrão e portátil.
Algumas implementações fornecem itoa () , mas não será a maioria, e possui uma interface um pouco ruim. Mas o código está por trás do link e deve permitir que você implemente seu próprio formatador com bastante facilidade.
fonte
Conversão genérica de uma instrução de qualquer tipo integral na representação de cadeia binária usando a biblioteca padrão :
Ou apenas:
std::cout << std::bitset<sizeof(num) * 8>(num);
fonte
Minha solução:
fonte
Baseado em @ de ideasman42 sugestão em sua resposta, esta é uma macro que fornece
int8
,16
,32
e64
versões, reutilizando aINT8
macro à repetição evitar.Isso gera:
Para facilitar a leitura, você pode alterar:
#define PRINTF_BINARY_SEPARATOR
para#define PRINTF_BINARY_SEPARATOR ","
ou#define PRINTF_BINARY_SEPARATOR " "
Isso produzirá:
ou
fonte
Usar:
Para mais ref., Consulte Como imprimir número binário via printf .
fonte
deve funcionar - não testado.
fonte
fonte
Em seguida, mostrará o layout da memória:
fonte
Aqui está uma pequena variação da solução da paniq que usa modelos para permitir a impressão de números inteiros de 32 e 64 bits:
E pode ser usado como:
Aqui está o resultado:
fonte