Posso stampare con printf come un numero esadecimale o ottale. Esiste un tag di formato da stampare come binario o base arbitraria?
Sto eseguendo gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Posso stampare con printf come un numero esadecimale o ottale. Esiste un tag di formato da stampare come binario o base arbitraria?
Sto eseguendo gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Risposte:
Hacky ma funziona per me:
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY(byte) \
(byte & 0x80 ? '1' : '0'), \
(byte & 0x40 ? '1' : '0'), \
(byte & 0x20 ? '1' : '0'), \
(byte & 0x10 ? '1' : '0'), \
(byte & 0x08 ? '1' : '0'), \
(byte & 0x04 ? '1' : '0'), \
(byte & 0x02 ? '1' : '0'), \
(byte & 0x01 ? '1' : '0')
printf("Leading text "BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(byte));
Per tipi multi-byte
printf("m: "BYTE_TO_BINARY_PATTERN" "BYTE_TO_BINARY_PATTERN"\n",
BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));
Purtroppo hai bisogno di tutte le citazioni extra. Questo approccio presenta i rischi di efficienza delle macro (non passare una funzione come argomento a BYTE_TO_BINARY
) ma evita i problemi di memoria e le invocazioni multiple di strcat in alcune delle altre proposte qui.
printf
cui quelli con static
buffer non possono.
%d
in %c
, perché dovrebbe essere ancora più veloce ( %d
deve eseguire la conversione digit-> char, mentre %c
genera semplicemente l'argomento
int
il sistema sia a 32 bit, la stampa di un singolo valore a 32 bit richiederà spazio per valori di 32 * 4 byte; totale di 128 byte. Che, a seconda delle dimensioni dello stack, può essere o meno un problema.
Stampa binaria per qualsiasi tipo di dati
//assumes little endian
void printBits(size_t const size, void const * const ptr)
{
unsigned char *b = (unsigned char*) ptr;
unsigned char 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("");
}
test
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);
return 0;
}
size_t i; for (i=size; i-- > 0; )
di evitare size_t
vs. int
mis-match.
ptr
(loop esterno); quindi per ogni bit il byte corrente (loop interno), maschera il byte dal bit corrente ( 1 << j
). Sposta quel diritto risultante in un byte contenente 0 ( 0000 0000b
) o 1 ( 0000 0001b
). Stampa il byte risultante printf con il formato %u
. HTH.
>
con size_t
e non quello >=
del commento per determinare quando terminare il ciclo.
>
e>=
con tipi non firmati. 0
è un caso limite senza segno e si verifica comunemente, a differenza della matematica firmata con meno comune INT_MAX/INT_MIN
.
Ecco un trucco rapido per dimostrare le tecniche per fare ciò che vuoi.
#include <stdio.h> /* printf */
#include <string.h> /* strcat */
#include <stdlib.h> /* strtol */
const char *byte_to_binary
(
int x
)
{
static char 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));
}
return 0;
}
strcat
è un metodo inefficiente per aggiungere un singolo carattere alla stringa su ogni passaggio del ciclo. Invece, aggiungi a char *p = b;
e sostituisci il ciclo interno con *p++ = (x & z) ? '1' : '0'
. z
dovrebbe iniziare da 128 (2 ^ 7) anziché 256 (2 ^ 8). Considerare l'aggiornamento per utilizzare un puntatore al buffer da utilizzare (per la sicurezza del thread), in modo simile a inet_ntoa()
.
strcat()
! Concordo sul fatto che strcat
probabilmente è più facile da capire rispetto al post-incremento di un puntatore senza riferimenti per il compito, ma anche i principianti devono sapere come utilizzare correttamente la libreria standard. Forse usare un array indicizzato per l'assegnazione sarebbe stata una buona dimostrazione (e funzionerà davvero, dato che b
non viene resettato a tutti gli zeri ogni volta che chiami la funzione).
printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4))
.
Normalmente non c'è un identificatore di conversione binaria in glibc.
È possibile aggiungere tipi di conversione personalizzati alla famiglia di funzioni printf () in glibc. Vedi register_printf_function per i dettagli. È possibile aggiungere una conversione% b personalizzata per uso personale, se semplifica il codice dell'applicazione per renderlo disponibile.
Ecco un esempio di come implementare formati di stampa personalizzati in glibc.
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]
C'è una nuova funzione di fare lo stesso, però: register_printf_specifier()
. Un esempio del nuovo utilizzo è disponibile qui: codereview.stackexchange.com/q/219994/200418
È possibile utilizzare una piccola tabella per migliorare la velocità 1 . Tecniche simili sono utili nel mondo incorporato, ad esempio, per invertire un byte:
const char *bit_rep[16] = {
[ 0] = "0000", [ 1] = "0001", [ 2] = "0010", [ 3] = "0011",
[ 4] = "0100", [ 5] = "0101", [ 6] = "0110", [ 7] = "0111",
[ 8] = "1000", [ 9] = "1001", [10] = "1010", [11] = "1011",
[12] = "1100", [13] = "1101", [14] = "1110", [15] = "1111",
};
void print_byte(uint8_t byte)
{
printf("%s%s", bit_rep[byte >> 4], bit_rep[byte & 0x0F]);
}
1 Mi riferisco principalmente ad applicazioni integrate in cui gli ottimizzatori non sono così aggressivi e la differenza di velocità è visibile.
Stampa il bit meno significativo e spostalo verso destra. In questo modo fino a quando l'intero diventa zero, la rappresentazione binaria viene stampata senza zeri iniziali ma in ordine inverso. Utilizzando la ricorsione, l'ordine può essere corretto abbastanza facilmente.
#include <stdio.h>
void print_binary(int number)
{
if (number) {
print_binary(number >> 1);
putc((number & 1) ? '1' : '0', stdout);
}
}
Per me, questa è una delle soluzioni più pulite al problema. Se ti piace il 0b
prefisso e un nuovo carattere di riga finale, ti suggerisco di racchiudere la funzione.
putc('0'+(number&1), stdout);
Sulla base di risposta di @William Whyte, questa è una macro che fornisce int8
, 16
, 32
e 64
le versioni, il riutilizzo della INT8
macro per evitare ripetizioni.
/* --- PRINTF_BYTE_TO_BINARY macro's --- */
#define PRINTF_BINARY_PATTERN_INT8 "%c%c%c%c%c%c%c%c"
#define PRINTF_BYTE_TO_BINARY_INT8(i) \
(((i) & 0x80ll) ? '1' : '0'), \
(((i) & 0x40ll) ? '1' : '0'), \
(((i) & 0x20ll) ? '1' : '0'), \
(((i) & 0x10ll) ? '1' : '0'), \
(((i) & 0x08ll) ? '1' : '0'), \
(((i) & 0x04ll) ? '1' : '0'), \
(((i) & 0x02ll) ? '1' : '0'), \
(((i) & 0x01ll) ? '1' : '0')
#define PRINTF_BINARY_PATTERN_INT16 \
PRINTF_BINARY_PATTERN_INT8 PRINTF_BINARY_PATTERN_INT8
#define PRINTF_BYTE_TO_BINARY_INT16(i) \
PRINTF_BYTE_TO_BINARY_INT8((i) >> 8), PRINTF_BYTE_TO_BINARY_INT8(i)
#define PRINTF_BINARY_PATTERN_INT32 \
PRINTF_BINARY_PATTERN_INT16 PRINTF_BINARY_PATTERN_INT16
#define PRINTF_BYTE_TO_BINARY_INT32(i) \
PRINTF_BYTE_TO_BINARY_INT16((i) >> 16), PRINTF_BYTE_TO_BINARY_INT16(i)
#define PRINTF_BINARY_PATTERN_INT64 \
PRINTF_BINARY_PATTERN_INT32 PRINTF_BINARY_PATTERN_INT32
#define PRINTF_BYTE_TO_BINARY_INT64(i) \
PRINTF_BYTE_TO_BINARY_INT32((i) >> 32), PRINTF_BYTE_TO_BINARY_INT32(i)
/* --- end macros --- */
#include <stdio.h>
int main() {
long long int flag = 1648646756487983144ll;
printf("My Flag "
PRINTF_BINARY_PATTERN_INT64 "\n",
PRINTF_BYTE_TO_BINARY_INT64(flag));
return 0;
}
Questo produce:
My Flag 0001011011100001001010110111110101111000100100001111000000101000
Per motivi di leggibilità, potresti voler aggiungere un separatore, ad esempio:
My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
PRINTF_BYTE_TO_BINARY_INT#
definisce da utilizzare facoltativamente.
Ecco una versione della funzione che non soffre di problemi di rientro o limiti sulla dimensione / tipo dell'argomento:
#define FMT_BUF_SIZE (CHAR_BIT*sizeof(uintmax_t)+1)
char *binary_fmt(uintmax_t x, char buf[static FMT_BUF_SIZE])
{
char *s = buf + FMT_BUF_SIZE;
*--s = 0;
if (!x) *--s = '0';
for(; x; x/=2) *--s = '0' + x%2;
return s;
}
Si noti che questo codice funzionerebbe altrettanto bene per qualsiasi base tra 2 e 10 se si sostituissero i 2 con la base desiderata. L'utilizzo è:
char tmp[FMT_BUF_SIZE];
printf("%s\n", binary_fmt(x, tmp));
Dov'è x
qualsiasi espressione integrale.
char *a = binary_fmt(x), *b = binary_fmt(y);
non funzioneranno come previsto. Forzare il chiamante a passare un buffer rende esplicito il requisito di archiviazione; il chiamante è ovviamente libero di usare un buffer statico se ciò è veramente desiderato, e quindi il riutilizzo dello stesso buffer diventa esplicito. Si noti inoltre che, nelle moderne ABI PIC, i buffer statici di solito costano più codice per l'accesso rispetto ai buffer nello stack.
const char* byte_to_binary( int x )
{
static char b[sizeof(int)*8+1] = {0};
int y;
long long z;
for (z=1LL<<sizeof(int)*8-1,y=0; z>0; z>>=1,y++)
{
b[y] = ( ((x & z) == z) ? '1' : '0');
}
b[y] = 0;
return b;
}
'1'
e '0'
invece di 49
e 48
nel tuo ternario. Inoltre, b
dovrebbe essere lungo 9 caratteri in modo che l'ultimo carattere possa rimanere un terminatore nullo.
static char b[9] = {0}
2. Dichiarazione mossa fuori dal giro: int z,y;
3. Aggiungere la finale pari a zero: b[y] = 0
. In questo modo non è necessaria alcuna reinizializzazione.
8
dovrebbero essere sostituiti da CHAR_BIT
.
Soluzione semplice e veloce:
void printbits(my_integer_type x)
{
for(int i=sizeof(x)<<3; i; i--)
putchar('0'+((x>>(i-1))&1));
}
Funziona con qualsiasi tipo di dimensione e per interi firmati e non firmati. "& 1" è necessario per gestire gli integri firmati poiché lo spostamento può comportare l'estensione dei segni.
Ci sono molti modi per farlo. Eccone uno semplicissimo per stampare 32 bit o n bit da un tipo a 32 bit con o senza segno (non mettere un negativo se firmato, solo stampare i bit effettivi) e nessun ritorno a capo. Si noti che i è decrementato prima del bit shift:
#define printbits_n(x,n) for (int i=n;i;i--,putchar('0'|(x>>i)&1))
#define printbits_32(x) printbits_n(x,32)
Che ne dici di restituire una stringa con i bit da memorizzare o stampare in seguito? È possibile allocare la memoria e restituirla e l'utente deve liberarla, oppure si restituisce una stringa statica ma verrà ostruita se viene richiamata nuovamente o da un altro thread. Entrambi i metodi mostrati:
char *int_to_bitstring_alloc(int x, int count)
{
count = count<1 ? sizeof(x)*8 : count;
char *pstr = malloc(count+1);
for(int i = 0; i<count; i++)
pstr[i] = '0' | ((x>>(count-1-i))&1);
pstr[count]=0;
return pstr;
}
#define BITSIZEOF(x) (sizeof(x)*8)
char *int_to_bitstring_static(int x, int count)
{
static char bitbuf[BITSIZEOF(x)+1];
count = (count<1 || count>BITSIZEOF(x)) ? BITSIZEOF(x) : count;
for(int i = 0; i<count; i++)
bitbuf[i] = '0' | ((x>>(count-1-i))&1);
bitbuf[count]=0;
return bitbuf;
}
Chiama con:
// memory allocated string returned which needs to be freed
char *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 else
char *pstr2 = int_to_bitstring_static(0x97e50ae6, 17);
printf("bits = 0b%s\n", pstr2);
Nessuna delle risposte precedentemente pubblicate è esattamente quello che stavo cercando, quindi ne ho scritto uno. È super semplice usare% B con il printf
!
/*
* File: main.c
* Author: Techplex.Engineer
*
* Created on February 14, 2012, 9:16 PM
*/
#include <stdio.h>
#include <stdlib.h>
#include <printf.h>
#include <math.h>
#include <string.h>
static int printf_arginfo_M(const struct printf_info *info, size_t n, int *argtypes) {
/* "%M" always takes one argument, a pointer to uint8_t[6]. */
if (n > 0) {
argtypes[0] = PA_POINTER;
}
return 1;
} /* printf_arginfo_M */
static int printf_output_M(FILE *stream, const struct printf_info *info, const void *const *args) {
int value = 0;
int len;
value = *(int **) (args[0]);
//Beginning of my code ------------------------------------------------------------
char buffer [50] = ""; //Is this bad?
char buffer2 [50] = ""; //Is this bad?
int bits = info->width;
if (bits <= 0)
bits = 8; // Default to 8 bits
int mask = pow(2, bits - 1);
while (mask > 0) {
sprintf(buffer, "%s", (((value & mask) > 0) ? "1" : "0"));
strcat(buffer2, buffer);
mask >>= 1;
}
strcat(buffer2, "\n");
// End of my code --------------------------------------------------------------
len = fprintf(stream, "%s", buffer2);
return len;
} /* printf_output_M */
int main(int argc, char** argv) {
register_printf_specifier('B', printf_output_M, printf_arginfo_M);
printf("%4B\n", 65);
return (EXIT_SUCCESS);
}
char* buffer = (char*) malloc(sizeof(char) * 50);
char *buffer = malloc(sizeof(*buffer) * 50);
Alcuni runtime supportano "% b" sebbene non sia uno standard.
Vedi anche qui per una discussione interessante:
http://bytes.com/forum/thread591027.html
HTH
Questo codice dovrebbe gestire le tue esigenze fino a 64 bit. Ho creato 2 funzioni pBin & pBinFill. Entrambi fanno la stessa cosa, ma pBinFill riempie gli spazi iniziali con fillChar. La funzione di test genera alcuni dati di test, quindi li stampa utilizzando la funzione.
char* pBinFill(long int x,char *so, char fillChar); // version with fill
char* pBin(long int x, char *so); // version without fill
#define kDisplayWidth 64
char* pBin(long int x,char *so)
{
char s[kDisplayWidth+1];
int i=kDisplayWidth;
s[i--]=0x00; // terminate string
do
{ // 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 string
return so;
}
char* pBinFill(long int x,char *so, char fillChar)
{ // fill in array from right to left
char s[kDisplayWidth+1];
int i=kDisplayWidth;
s[i--]=0x00; // terminate string
do
{ // 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 pBin
long int 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 = 0b00000000000000000000000000000001
00000011 = 0x00000b = 0b00000000000000000000000000001011
00000121 = 0x000079 = 0b00000000000000000000000001111001
00001331 = 0x000533 = 0b00000000000000000000010100110011
00014641 = 0x003931 = 0b00000000000000000011100100110001
00161051 = 0x02751b = 0b00000000000000100111010100011011
01771561 = 0x1b0829 = 0b00000000000110110000100000101001
19487171 = 0x12959c3 = 0b00000001001010010101100111000011
width
invece!
Esiste un convertitore printf per stampare in formato binario?
La printf()
famiglia è in grado di stampare solo nelle basi 8, 10 e 16 utilizzando direttamente gli identificatori standard. Suggerisco di creare una funzione che converta il numero in una stringa per esigenze particolari del codice.
Per stampare in qualsiasi base [2-36]
Tutte le altre risposte finora hanno almeno una di queste limitazioni.
Utilizzare la memoria statica per il buffer di ritorno. Ciò limita il numero di volte in cui la funzione può essere utilizzata come argomento printf()
.
Allocare memoria che richiede il codice chiamante per liberare i puntatori.
Richiede che il codice chiamante fornisca esplicitamente un buffer adatto.
Chiama printf()
direttamente. Questo obbliga una nuova funzione per la a fprintf()
, sprintf()
, vsprintf()
, etc.
Utilizzare un intervallo intero ridotto.
Quanto segue non presenta alcuna delle suddette limitazioni . Richiede C99 o versioni successive e l'utilizzo di "%s"
. Utilizza un valore letterale composto per fornire lo spazio buffer. Non ha problemi con più chiamate in 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 beginning
return 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));
return 0;
}
Produzione
1020304 5060708
1000000100000001100000100 101000001100000011100001000
100401404
A2F44
Forse un po 'OT, ma se ne hai bisogno solo per il debug per capire o ripercorrere alcune operazioni binarie che stai facendo, potresti dare un'occhiata a wcalc (una semplice calcolatrice console). Con le opzioni -b ottieni un output binario.
per esempio
$ wcalc -b "(256 | 3) e 0xff" = 0b11
ruby -e 'printf("%b\n", 0xabc)'
, dc
seguite da 2o
seguite da 0x123p
e così via.
Non esiste alcuna funzione di formattazione nella libreria standard C per generare binari del genere. Tutte le operazioni di formattazione supportate dalla famiglia printf riguardano il testo leggibile dall'uomo.
Potrebbe essere utile la seguente funzione ricorsiva:
void bin(int n)
{
/* Step 1 */
if (n > 1)
bin(n/2);
/* Step 2 */
printf("%d", n % 2);
}
Ho ottimizzato la soluzione migliore per dimensioni e C ++ e sono arrivato a questa soluzione:
inline std::string format_binary(unsigned int x)
{
static char b[33];
b[32] = '\0';
for (int z = 0; z < 32; z++) {
b[31-z] = ((x>>z) & 0x1) ? '1' : '0';
}
return b;
}
std::string
), è possibile eliminare l' static
array. Il modo più semplice sarebbe quello di rilasciare il static
qualificatore e renderlo b
locale alla funzione.
((x>>z) & 0x01) + '0'
è sufficiente.
Questo approccio ha come attributi:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define for_endian(size) for (int i = 0; i < size; ++i)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define for_endian(size) for (int i = size - 1; i >= 0; --i)
#else
#error "Endianness not detected"
#endif
#define printb(value) \
({ \
typeof(value) _v = value; \
__printb((typeof(_v) *) &_v, sizeof(_v)); \
})
void __printb(void *value, size_t size)
{
uint8_t byte;
size_t blen = sizeof(byte) * 8;
uint8_t bits[blen + 1];
bits[blen] = '\0';
for_endian(size) {
byte = ((uint8_t *) value)[i];
memset(bits, '0', blen);
for (int j = 0; byte && j < blen; ++j) {
if (byte & 0x80)
bits[j] = '1';
byte <<= 1;
}
printf("%s ", bits);
}
printf("\n");
}
int main(void)
{
uint8_t c1 = 0xff, c2 = 0x44;
uint8_t c3 = c1 + c2;
printb(c1);
printb((char) 0xff);
printb((short) 0xff);
printb(0xff);
printb(c2);
printb(0x44);
printb(0x4411ff01);
printb((uint16_t) c3);
printf("\n");
return 0;
}
$ ./printb
11111111
11111111
00000000 11111111
00000000 00000000 00000000 11111111
01000100
00000000 00000000 00000000 01000100
01000100 00010001 11111111 00000001
00000000 01000011
Ho usato un altro approccio ( bitprint.h ) per riempire una tabella con tutti i byte (come stringhe di bit) e stamparli in base al byte di input / indice. Vale la pena dare un'occhiata.
void
print_binary(unsigned int n)
{
unsigned int 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');
}
}
Mi è piaciuto il codice di Paniq, il buffer statico è una buona idea. Tuttavia, non riesce se si desidera più formati binari in un singolo printf () perché restituisce sempre lo stesso puntatore e sovrascrive l'array.
Ecco un drop-in in stile C che ruota il puntatore su un buffer diviso.
char *
format_binary(unsigned int x)
{
#define MAXLEN 8 // width of output format
#define MAXCNT 4 // count per printf statement
static char fmtbuf[(MAXLEN+1)*MAXCNT];
static int 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;
}
count
raggiunto MAXCNT - 1
, l'incremento successivo di count
lo renderebbe MAXCNT
invece di zero, il che provocherebbe un accesso fuori dai limiti dell'array. Avresti dovuto count = (count + 1) % MAXCNT
.
MAXCNT + 1
chiamate a questa funzione in un unico printf
. In generale, se vuoi dare l'opzione per più di 1 cosa, rendila infinita. Numeri come 4 potrebbero solo causare problemi.
Una conversione generica di un'istruzione di qualsiasi tipo integrale nella rappresentazione di stringa binaria utilizzando la libreria standard :
#include <bitset>
MyIntegralType num = 10;
print("%s\n",
std::bitset<sizeof(num) * 8>(num).to_string().insert(0, "0b").c_str()
); // prints "0b1010\n"
O semplicemente: std::cout << std::bitset<sizeof(num) * 8>(num);
La mia soluzione:
long unsigned int i;
for(i = 0u; i < sizeof(integer) * CHAR_BIT; i++) {
if(integer & LONG_MIN)
printf("1");
else
printf("0");
integer <<= 1;
}
printf("\n");
Sulla base di @ ideasman42 suggestione nella sua risposta, questa è una macro che fornisce int8
, 16
, 32
e 64
le versioni, il riutilizzo della INT8
macro per evitare ripetizioni.
/* --- PRINTF_BYTE_TO_BINARY macro's --- */
#define PRINTF_BINARY_SEPARATOR
#define PRINTF_BINARY_PATTERN_INT8 "%c%c%c%c%c%c%c%c"
#define PRINTF_BYTE_TO_BINARY_INT8(i) \
(((i) & 0x80ll) ? '1' : '0'), \
(((i) & 0x40ll) ? '1' : '0'), \
(((i) & 0x20ll) ? '1' : '0'), \
(((i) & 0x10ll) ? '1' : '0'), \
(((i) & 0x08ll) ? '1' : '0'), \
(((i) & 0x04ll) ? '1' : '0'), \
(((i) & 0x02ll) ? '1' : '0'), \
(((i) & 0x01ll) ? '1' : '0')
#define PRINTF_BINARY_PATTERN_INT16 \
PRINTF_BINARY_PATTERN_INT8 PRINTF_BINARY_SEPARATOR PRINTF_BINARY_PATTERN_INT8
#define PRINTF_BYTE_TO_BINARY_INT16(i) \
PRINTF_BYTE_TO_BINARY_INT8((i) >> 8), PRINTF_BYTE_TO_BINARY_INT8(i)
#define PRINTF_BINARY_PATTERN_INT32 \
PRINTF_BINARY_PATTERN_INT16 PRINTF_BINARY_SEPARATOR PRINTF_BINARY_PATTERN_INT16
#define PRINTF_BYTE_TO_BINARY_INT32(i) \
PRINTF_BYTE_TO_BINARY_INT16((i) >> 16), PRINTF_BYTE_TO_BINARY_INT16(i)
#define PRINTF_BINARY_PATTERN_INT64 \
PRINTF_BINARY_PATTERN_INT32 PRINTF_BINARY_SEPARATOR PRINTF_BINARY_PATTERN_INT32
#define PRINTF_BYTE_TO_BINARY_INT64(i) \
PRINTF_BYTE_TO_BINARY_INT32((i) >> 32), PRINTF_BYTE_TO_BINARY_INT32(i)
/* --- end macros --- */
#include <stdio.h>
int main() {
long long int flag = 1648646756487983144ll;
printf("My Flag "
PRINTF_BINARY_PATTERN_INT64 "\n",
PRINTF_BYTE_TO_BINARY_INT64(flag));
return 0;
}
Questo produce:
My Flag 0001011011100001001010110111110101111000100100001111000000101000
Per la leggibilità è possibile modificare: #define PRINTF_BINARY_SEPARATOR
a#define PRINTF_BINARY_SEPARATOR ","
o#define PRINTF_BINARY_SEPARATOR " "
Questo produrrà:
My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
o
My Flag 00010110 11100001 00101011 01111101 01111000 10010000 11110000 00101000
Uso:
char buffer [33];
itoa(value, buffer, 2);
printf("\nbinary: %s\n", buffer);
Per ulteriori informazioni, vedere Come stampare il numero binario tramite printf .
void print_ulong_bin(const unsigned long * const var, int bits) {
int i;
#if defined(__LP64__) || defined(_LP64)
if( (bits > 64) || (bits <= 0) )
#else
if( (bits > 32) || (bits <= 0) )
#endif
return;
for(i = 0; i < bits; i++) {
printf("%lu", (*var >> (bits - 1 - i)) & 0x01);
}
}
dovrebbe funzionare - non testato.
/* 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" */
Successivamente verrà mostrato il layout di memoria:
#include <limits>
#include <iostream>
#include <string>
using namespace std;
template<class T> string binary_text(T dec, string byte_separator = " ") {
char* pch = (char*)&dec;
string res;
for (int i = 0; i < sizeof(T); i++) {
for (int j = 1; j < 8; j++) {
res.append(pch[i] & 1 ? "1" : "0");
pch[i] /= 2;
}
res.append(byte_separator);
}
return res;
}
int main() {
cout << binary_text(5) << endl;
cout << binary_text(.1) << endl;
return 0;
}
Ecco una piccola variante della soluzione di paniq che utilizza modelli per consentire la stampa di numeri interi a 32 e 64 bit:
template<class T>
inline std::string format_binary(T x)
{
char b[sizeof(T)*8+1] = {0};
for (size_t z = 0; z < sizeof(T)*8; z++)
b[sizeof(T)*8-1-z] = ((x>>z) & 0x1) ? '1' : '0';
return std::string(b);
}
E può essere usato come:
unsigned int value32 = 0x1e127ad;
printf( " 0x%x: %s\n", value32, format_binary(value32).c_str() );
unsigned long long value64 = 0x2e0b04ce0;
printf( "0x%llx: %s\n", value64, format_binary(value64).c_str() );
Ecco il risultato:
0x1e127ad: 00000001111000010010011110101101
0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000