web-dev-qa-db-de.com

Gibt es einen Printf-Konverter, um im Binärformat zu drucken?

Ich kann mit printf als Hex- oder Oktalzahl drucken. Gibt es ein Format-Tag, das binär oder als beliebige Basis gedruckt werden kann? 

Ich laufe gcc.

printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
368
Brian

Hacky aber funktioniert für mich:

#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));

Für Multi-Byte-Typen 

printf("m: "BYTE_TO_BINARY_PATTERN" "BYTE_TO_BINARY_PATTERN"\n",
  BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));

Sie benötigen leider alle zusätzlichen Zitate. Dieser Ansatz birgt die Effizienzrisiken von Makros (übergeben Sie keine Funktion als Argument für BYTE_TO_BINARY), vermeidet jedoch die Speicherprobleme und die mehrfachen Aufrufe von strcat in einigen der anderen Vorschläge hier.

225
William Whyte

Binary für jeden Datentyp drucken

//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("");
}

prüfung

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;
}
190
user295190

Hier ist ein kurzer Hack, um Techniken zu demonstrieren, um zu tun, was Sie wollen. 

#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;
}
149
EvilTeach

Normalerweise gibt es in glibc keinen binären Konvertierungsspezifizierer.

Es ist möglich, benutzerdefinierte Konvertierungstypen zur printf () - Funktionsfamilie in glibc hinzuzufügen. Siehe register_printf_function für Details. Sie können eine benutzerdefinierte% b-Konvertierung für Ihre eigene Verwendung hinzufügen, wenn dadurch der Anwendungscode vereinfacht wird, damit er verfügbar ist.

Hier ist ein Beispiel , wie man ein benutzerdefiniertes printf-Format in glibc implementiert.

77
DGentry

Sie können einen kleinen Tisch verwenden, um die Geschwindigkeit zu verbessern1. Ähnliche Techniken sind beispielsweise in der eingebetteten Welt nützlich, um ein Byte zu invertieren:

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 Ich beziehe mich hauptsächlich auf eingebettete Anwendungen, bei denen Optimizer nicht so aggressiv sind und der Geschwindigkeitsunterschied sichtbar ist.

30
Shahbaz

Basierend auf der Antwort von @William Whyte ist dies ein Makro, das int8, 16, 32 & 64-Versionen bereitstellt, wobei das INT8-Makro wiederverwendet wird, um Wiederholungen zu vermeiden.

/* --- 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;
}

Dies gibt aus:

My Flag 0001011011100001001010110111110101111000100100001111000000101000

Zur besseren Lesbarkeit können Sie ein Trennzeichen hinzufügen, z. B. für:

My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
17
ideasman42

Hier ist eine Version der Funktion, die nicht an Problemen mit der Wiedereintrittsfähigkeit oder an Einschränkungen der Größe/des Typs des Arguments leidet:

#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;
}

Beachten Sie, dass dieser Code für jede Basis zwischen 2 und 10 genauso gut funktionieren würde, wenn Sie nur die 2 durch die gewünschte Basis ersetzen. Verwendung ist:

char tmp[FMT_BUF_SIZE];
printf("%s\n", binary_fmt(x, tmp));

Dabei ist x ein integraler Ausdruck.

16
R..

Drucken Sie das niedrigstwertige Bit und verschieben Sie es nach rechts. Wenn Sie dies tun, bis die ganze Zahl Null wird, wird die binäre Darstellung ohne führende Nullen gedruckt, jedoch in umgekehrter Reihenfolge. Durch Rekursion kann die Reihenfolge sehr leicht korrigiert werden.

#include <stdio.h>

void print_binary(int number)
{
    if (number) {
        print_binary(number >> 1);
        putc((number & 1) ? '1' : '0', stdout);
    }
}

Für mich ist dies eine der saubersten Lösungen für das Problem. Wenn Sie das 0b-Präfix und ein abschließendes neues Zeilenzeichen mögen, schlage ich vor, die Funktion einzuhüllen.

Online Demo

14
danijar
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;
}
11
works better

Einige Laufzeiten unterstützen "% b", obwohl dies kein Standard ist.

Siehe auch hier für eine interessante Diskussion:

http://bytes.com/forum/thread591027.html

HTH

8
rlerallut

Keine der zuvor veröffentlichten Antworten ist genau das, wonach ich gesucht habe, also habe ich eine geschrieben. Es ist sehr einfach,% B mit der printf zu verwenden!

    /*
     * 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);
    }
8

Dieser Code sollte Ihren Anforderungen bis zu 64 Bit entsprechen. __ Ich habe die beiden Funktionen pBin und pBinFill erstellt. Beide machen dasselbe, aber pBinFill füllt die führenden Leerzeichen mit fillChar ..__ aus: Die Testfunktion generiert einige Testdaten und druckt sie dann mit der Funktion aus.



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
7
mrwes

Vielleicht ein bisschen OT, aber wenn Sie dies nur für das Debuggen benötigen, um einige binäre Operationen, die Sie gerade ausführen, zu verstehen oder zurückzuverfolgen, werfen Sie einen Blick auf wcalc (einen einfachen Konsolenrechner). Mit der Option -b erhalten Sie eine binäre Ausgabe.

z.B.

 $ wcalc -b "(256 | 3) & 0xff" 
 = 0b11 
6
quinmars

Gibt es einen Printf-Konverter, um im Binärformat zu drucken?

Die printf()-Familie kann nur in Basis 8, 10 und 16 unter Verwendung der Standardspezifikationen direkt drucken. Ich empfehle, eine Funktion zu erstellen, die die Zahl in eine Zeichenfolge pro Code umwandelt.


In einer beliebigen Basis drucken [2-36]

Alle anderen Antworten haben bisher mindestens eine dieser Einschränkungen.

  1. Verwenden Sie statischen Speicher für den Rückgabepuffer. Dies begrenzt die Anzahl, wie oft die Funktion als Argument für printf() verwendet werden darf.

  2. Weisen Sie Speicher zu, der den aufrufenden Code benötigt, um Zeiger frei zu geben.

  3. Fordern Sie den aufrufenden Code an, um explizit einen geeigneten Puffer bereitzustellen.

  4. Rufen Sie printf() direkt auf. Dies erfordert eine neue Funktion für fprintf(), sprintf(), vsprintf() usw.

  5. Verwenden Sie einen reduzierten ganzzahligen Bereich.

Das Folgende hat keine der obigen Einschränkungen. Es erfordert C99 oder höher und die Verwendung von "%s". Es verwendet ein zusammengesetztes Literal , um den Pufferplatz bereitzustellen. Es hat keine Probleme mit mehreren Anrufen in einer 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;
}

Ausgabe

1020304 5060708
1000000100000001100000100 101000001100000011100001000
100401404
A2F44
5
chux

Es gibt keine Formatierungsfunktion in der C-Standardbibliothek, um eine solche Binärdatei auszugeben. Alle Formatierungsvorgänge, die von der printf-Familie unterstützt werden, richten sich auf vom Menschen lesbaren Text.

5
Florian Bösch

Die folgende rekursive Funktion kann nützlich sein:

void bin(int n)
{
    /* Step 1 */
    if (n > 1)
        bin(n/2);
    /* Step 2 */
    printf("%d", n % 2);
}
5
kapil
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');
    }

}

Ich habe die Top-Lösung für Größe und C++ optimiert und habe folgende Lösung gefunden:

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;
}
4
paniq

Basierend auf dem Vorschlag von @ ideasman42 in seiner Antwort ist dies ein Makro, das int8, 16, 32 & 64-Versionen bereitstellt und das INT8-Makro wiederverwendet, um Wiederholungen zu vermeiden.

/* --- 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;
}

Dies gibt aus:

My Flag 0001011011100001001010110111110101111000100100001111000000101000

Zur besseren Lesbarkeit können Sie Folgendes ändern: #define PRINTF_BINARY_SEPARATOR in #define PRINTF_BINARY_SEPARATOR "," oder #define PRINTF_BINARY_SEPARATOR " "

Dies wird ausgegeben:

My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000

oder

My Flag 00010110 11100001 00101011 01111101 01111000 10010000 11110000 00101000
3
Et7f3XIV

Drucken Sie Bits von jedem Typ mit weniger Code und Ressourcen

Dieser Ansatz hat folgende Attribute:

  • Funktioniert mit Variablen und Literalen.
  • Iteriert nicht alle Bits, wenn dies nicht erforderlich ist.
  • Rufe printf nur auf, wenn ein Byte abgeschlossen ist (nicht für alle Bits unnötig).
  • Funktioniert für jeden Typ.
  • Funktioniert mit wenig und großer Endianness (verwendet GCC #defines zur Überprüfung).
  • Verwendet typeof (), das kein C-Standard ist, aber weitgehend definiert ist.
#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;
}

Ausgabe

$ ./printb 
11111111 
11111111 
00000000 11111111 
00000000 00000000 00000000 11111111 
01000100 
00000000 00000000 00000000 01000100 
01000100 00010001 11111111 00000001 
00000000 01000011 

Ich habe die Methode another ( bitprint.h ) verwendet, um eine Tabelle mit allen Bytes (als Bitfolgen) zu füllen und sie basierend auf dem Eingabe-/Indexbyte zu drucken. Es lohnt sich, einen Blick darauf zu werfen.

3
Geyslan G. Bem

Meine Lösung:

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");
3
SarahGaidi

Kein Standard und tragbarer Weg.

Einige Implementierungen bieten itoa () , sind aber in den meisten Fällen nicht vorhanden, und sie haben eine etwas dürre Oberfläche. Der Code steht jedoch hinter dem Link und sollte es Ihnen leicht machen, Ihr eigenes Formatierungsprogramm zu implementieren.

3
wnoise

Der Code von paniq hat mir gefallen, der statische Puffer ist eine gute Idee. Es schlägt jedoch fehl, wenn Sie mehrere Binärformate in einem einzigen printf () verwenden möchten, da es immer denselben Zeiger zurückgibt und das Array überschreibt. 

Hier ist ein Drop-In im C-Stil, das den Zeiger auf einem Split-Puffer dreht.

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;
}
3
eMPee584

Eine generische Anweisung konvertiert einen beliebigen ganzzahligen Typ in die binäre Zeichenfolgendarstellung mithilfe der Bibliothek 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"

Oder einfach:std::cout << std::bitset<sizeof(num) * 8>(num);

2
luart

So habe ich es für einen vorzeichenlosen Int gemacht

void printb(unsigned int v) {
    unsigned int i, s = 1<<((sizeof(v)<<3)-1); // s = only most significant bit at 1
    for (i = s; i; i>>=1) printf("%d", v & i || 0 );
}
2
andre.barata

Eine kleine Utility-Funktion in C, um dies zu tun, während ein wenig Manipulationsproblem gelöst wird. Dies geht über den String, wobei jedes gesetzte Bit unter Verwendung einer Maske geprüft wird (1 <.

void
printStringAsBinary(char * input)
{
    char * temp = input;
    int i = 7, j =0;;
    int inputLen = strlen(input);

    /* Go over the string, check first bit..bit by bit and print 1 or 0
     **/

    for (j = 0; j < inputLen; j++) {
        printf("\n");
        while (i>=0) {
            if (*temp & (1 << i)) {
               printf("1");
            } else {
                printf("0");
            }
            i--;
        }
        temp = temp+1;
        i = 7;
        printf("\n");
    }
}
2
Gaurav Sinha

Next zeigt Ihnen das Speicherlayout:

#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;
}
2
Yola
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);
        }
}

sollte funktionieren - ungeprüft.

2
olli
#include <stdio.h>
#include <conio.h>

void main()
{
    clrscr();
    printf("Welcome\n\n\n");
    unsigned char x='A';
    char ch_array[8];
    for(int i=0; x!=0; i++)
    {
        ch_array[i] = x & 1;
        x = x >>1;
    }
    for(--i; i>=0; i--)
        printf("%d", ch_array[i]);

    getch();
}
2
rakesh jha

Noch eine andere Methode, um binär zu drucken: Konvertiere die Ganzzahl zuerst .

Um 6 binär zu drucken, ändern Sie 6 in 110 und drucken Sie dann "110".

Umgeht char buf[] Probleme.
printf() Formatbezeichner, Flags und Felder wie "%08lu", "%*lX" sind weiterhin ohne weiteres verwendbar.
Diese Methode ist nicht nur binär (Basis 2), sondern auch auf andere Basen bis 16 erweiterbar.
Begrenzt auf kleinste ganzzahlige Werte. 

#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>

unsigned long char_to_bin10(char ch) {
  unsigned char uch = ch;
  unsigned long sum = 0;
  unsigned long power = 1;
  while (uch) {
    if (uch & 1) {
      sum += power;
      }
   power *= 10;
   uch /= 2;
  }
  return sum;
}

uint64_t uint16_to_bin16(uint16_t u) {
  uint64_t sum = 0;
  uint64_t power = 1;
  while (u) {
    if (u & 1) {
      sum += power;
      }
    power *= 16;
    u /= 2;
  }
  return sum;
}

void test(void) {
  printf("%lu\n", char_to_bin10(0xF1));
  // 11110001
  printf("%" PRIX64 "\n", uint16_to_bin16(0xF731));
  // 1111011100110001
}
2
chux

Hier ist eine kleine Variation der Lösung von paniq , die Vorlagen zum Drucken von Ganzzahlen mit 32 und 64 Bit verwendet:

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);
}

Und kann verwendet werden wie:

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() );

Hier ist das Ergebnis:

  0x1e127ad: 00000001111000010010011110101101
0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000
2
Leo

Ich möchte nur meine Lösung posten. Es wird verwendet, um Nullen und Einsen eines Bytes abzurufen, aber der Aufruf dieser Funktion kann einige Male für größere Datenblöcke verwendet werden. Ich verwende es für 128 Bit oder größere Strukturen. Sie können es auch ändern, um size_t als Eingabeparameter und Zeiger auf die Daten zu verwenden, die Sie drucken möchten, sodass es unabhängig von der Größe sein kann. Aber es funktioniert für mich gut, so wie es ist.

void print_binary(unsigned char c)
{
 unsigned char i1 = (1 << (sizeof(c)*8-1));
 for(; i1; i1 >>= 1)
      printf("%d",(c&i1)!=0);
}

void get_binary(unsigned char c, unsigned char bin[])
{
 unsigned char i1 = (1 << (sizeof(c)*8-1)), i2=0;
 for(; i1; i1>>=1, i2++)
      bin[i2] = ((c&i1)!=0);
}
2
Marko
/* 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" */
2
Ben Cordero

Es gibt auch eine Idee, die Zahl in ein Hexadezimal-Format umzuwandeln und dann jede Hexadezimal-Verschlüsselung in vier "Bits" (Einsen und Nullen) zu decodieren. sprintf kann für uns Bitoperationen ausführen:

const char* binary(int n) {
  static const char binnums[16][5] = { "0000","0001","0010","0011",
    "0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111" };
  static const char* hexnums = "0123456789abcdef";
  static char inbuffer[16], outbuffer[4*16];
  const char *i;
  sprintf(inbuffer,"%x",n); // hexadecimal n -> inbuffer
  for(i=inbuffer; *i!=0; ++i) { // for each hexadecimal cipher
    int d = strchr(hexnums,*i) - hexnums; // store its decimal value to d
    char* o = outbuffer+(i-inbuffer)*4; // shift four characters in outbuffer
    sprintf(o,"%s",binnums[d]); // place binary value of d there
  }
  return strchr(outbuffer,'1'); // omit leading zeros
}

puts(binary(42)); // outputs 101010
1
Jan Turoň

Benutzen:

char buffer [33];
itoa(value, buffer, 2);
printf("\nbinary: %s\n", buffer);

Weitere Informationen finden Sie unter So drucken Sie die Binärzahl über printf.

1
kapilddit

Mach eine Funktion und rufe sie auf

display_binary(int n)
{
    long int arr[32];
    int arr_counter=0;
    while(n>=1)
    {
        arr[arr_counter++]=n%2;
        n/=2;
    }
    for(int i=arr_counter-1;i>=0;i--)
    {
        printf("%d",arr[i]);
    }
}
1
Esann

Vielleicht findet jemand diese Lösung nützlich:

void print_binary(int number, int num_digits) {
    int digit;
    for(digit = num_digits - 1; digit >= 0; digit--) {
        printf("%c", number & (1 << digit) ? '1' : '0');
    }
}
1
Kresimir
void DisplayBinary(unsigned int n)
{
    int l = sizeof(n) * 8;
    for (int i = l - 1 ; i >= 0; i--) {
        printf("%x", (n & (1 << i)) >> i);
    }
}
1
Rassoul
void DisplayBinary(int n)
{
    int arr[8];
    int top =-1;
    while (n)
    {
        if (n & 1)
            arr[++top] = 1;
        else
            arr[++top] = 0;

        n >>= 1;
    }
    for (int i = top ; i > -1;i--)
    {
        printf("%d",arr[i]);
    }
    printf("\n");
}
1
Akhil

Schnelle und einfache Lösung:

void printbits(my_integer_type x)
{
    for(int i=sizeof(x)<<3; i; i--)
        putchar('0'+((x>>(i-1))&1));
}

Funktioniert für jeden Größentyp und für signierte und unsignierte Ints. '& 1' wird benötigt, um vorzeichenbehaftete Ints zu behandeln, da die Verschiebung evtl. Vorzeichenerweiterung durchführen kann.

Es gibt so viele Möglichkeiten, dies zu tun. Hier ist ein supereinfacher Ausdruck für das Drucken von 32 Bit oder n Bit aus einem 32-Bit-Typ mit Vorzeichen (ohne Vorzeichen mit einem negativen Wert, nur die tatsächlichen Bits) und kein Wagenrücklauf. Beachten Sie, dass i vor der Bitverschiebung dekrementiert wird:

#define printbits_n(x,n) for (int i=n;i;i--,putchar('0'|(x>>i)&1))
#define printbits_32(x) printbits_n(x,32)

Wie wäre es, wenn Sie einen String mit den Bits zurückgeben, um ihn später zu speichern oder zu drucken? Sie können den Speicher entweder zuweisen und zurückgeben, und der Benutzer muss ihn freigeben, oder Sie geben eine statische Zeichenfolge zurück, die jedoch bei erneutem Aufruf oder durch einen anderen Thread blockiert wird. Beide Methoden gezeigt:

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;
}

Anrufen mit:

// 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);
0
Robotbugs

Selbst für Laufzeitbibliotheken, die% b unterstützen, scheint es nur für ganzzahlige Werte zu sein.

Wenn Sie Gleitkommawerte binär drucken möchten, habe ich Code geschrieben, den Sie unter http://www.exploringbinary.com/converting-floating-point-numbers-to-binary-strings-in-c/ finden. .

0
Rick Regan

Hier ist eine sehr einfache:

int print_char_to_binary(char ch)
{
    int i;
    for (i=7; i>=0; i--)
        printf("%hd ", ((ch & (1<<i))>>i));
    printf("\n");
    return 0;
}
0
hiteshradia

Gibt es einen Printf-Konverter, um im Binärformat zu drucken?

Es gibt keinen Standard-Printf-Formatbezeichner, um eine "binäre" Ausgabe durchzuführen. Hier ist die Alternative, die ich mir ausgedacht hatte, als ich sie brauchte.

Mine funktioniert für jede Basis von 2 bis 36. Es fächert die Ziffern in den aufrufenden Rahmen rekursiver Aufrufe auf, bis es eine Ziffer erreicht, die kleiner als die Basis ist. Dann "durchquert" er rückwärts, füllt die Puffer vorwärts und kehrt zurück. Der Rückgabewert ist die verwendete Größe oder -1, wenn der Puffer nicht groß genug ist, um die Zeichenfolge aufzunehmen.

int conv_rad (int num, int rad, char *s, int n) {
    char *vec = "0123456789" "ABCDEFGHIJKLM" "NOPQRSTUVWXYZ";
    int off;
    if (n == 0) return 0;
    if (num < rad) { *s = vec[num]; return 1; }
    off = conv_rad(num/rad, rad, s, n);
    if ((off == n) || (off == -1)) return -1;
    s[off] = vec[num%rad];
    return off+1;
}

Eine große Einschränkung: Diese Funktion wurde für die Verwendung von "Pascal" -Styles entwickelt, die ihre Länge tragen. Folglich schreibt conv_rad, wie geschrieben, den Puffer nicht. Für allgemeinere C-Verwendungen wird wahrscheinlich ein einfacher Wrapper benötigt, um die Beendigung zu beenden. Oder ändern Sie zum Drucken einfach die Zuweisungen in putchar()s.

0
luser droog
void binario(int num) {
  for(int i=0;i<32;i++){
    (num&(1<i))? printf("1"):
        printf("0");
  }  
  printf("\n");
}
0
GutiMac

Die folgende Funktion gibt eine binäre Darstellung einer gegebenen vorzeichenlosen Ganzzahl unter Verwendung der Zeigerarithmetik ohne führende Nullen zurück: 

const char* toBinaryString(unsigned long num)
{
    static char buffer[CHAR_BIT*sizeof(num)+1];
    char* pBuffer = &buffer[sizeof(buffer)-1];

    do *--pBuffer = '0' + (num & 1);
    while (num >>= 1);
    return pBuffer;
}

Beachten Sie, dass keine Notwendigkeit besteht, NUL als Terminator festzulegen, da buffer ein Objekt mit statischer Speicherdauer darstellt, das bereits mit Nullen gefüllt ist.

Dies kann leicht an unsigned long long (oder eine andere vorzeichenlose Ganzzahl) angepasst werden, indem einfach der Typ des num-Formalparameters geändert wird.

Der CHAR_BIT erfordert, dass <limits.h> enthalten ist.

Hier ist ein Beispiel für eine Verwendung:

int main(void)
{
    printf(">>>%20s<<<\n", toBinaryString(1));
    printf(">>>%-20s<<<\n", toBinaryString(254));
    return 0;
}

mit der gewünschten Ausgabe als:

>>>                   1<<<
>>>11111110            <<<
void PrintBinary( int Value, int Places, char* TargetString)
{
    int Mask;

    Mask = 1 << Places;

    while( Places--) {
        Mask >>= 1; /* Preshift, because we did one too many above */
        *TargetString++ = (Value & Mask)?'1':'0';
    }
    *TargetString = 0; /* Null terminator for C string */
}

Die aufrufende Funktion "besitzt" den String ...:

char BinaryString[17];
...
PrintBinary( Value, 16, BinaryString);
printf( "yadda yadda %s yadda...\n", BinaryString);

Abhängig von Ihrer CPU werden die meisten Operationen in PrintBinary mit einer oder sehr wenigen Maschinenanweisungen ausgeführt.

0
Adam

Es ist vielleicht nicht sehr effizient, aber es ist ziemlich einfach. Versuche dies:

tmp1 = 1;
while(inint/tmp1 > 1) {
    tmp1 <<= 1;
}
do {
    printf("%d", tmp2=inint/tmp1);
    inint -= tmp1*tmp2;
} while((tmp1 >>= 1) > 0);
printf(" ");
0
Moses

Verwenden Sie die folgende Funktion:

void conbin(int num){  
        if(num != 0)
        {
            conbin(num >> 1);     
            if (num & 1){
            printf("1");
            }
            else{
            printf("0");
            }
        }
    }
0
kapilddit