Apakah ada konverter printf untuk mencetak dalam format biner?

Saya dapat mencetak dengan printf sebagai bilangan heksa atau oktal. Apakah ada tag format untuk mencetak sebagai biner, atau basis sembarang?

Saya menjalankan gcc.

printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Mengomentari pertanyaan (6)

Hacky tapi bekerja untuk saya.

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

Untuk tipe multi-byte

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

Sayangnya kau butuh semua kutipan tambahan. Pendekatan ini memiliki risiko efisiensi dari makro (jangan lulus sebuah fungsi sebagai argumen ke `BYTE_Tapi menghindari masalah memori dan beberapa undangan strcat dalam beberapa proposal lain di sini.

Komentar (8)

Cetak Binari untuk Setiap Datatype

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

uji

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;
}
Komentar (9)

Berikut adalah hack cepat untuk menunjukkan teknik untuk melakukan apa yang Anda inginkan.

#include       /* printf */
#include      /* strcat */
#include      /* 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;
}
Komentar (13)

There isn't a binary conversion specifier in glibc normally.

It is possible to add custom conversion types to the printf() family of functions in glibc. See register_printf_function for details. You could add a custom %b conversion for your own use, if it simplifies the application code to have it available.

Here is an example of how to implement a custom printf formats in glibc.

Komentar (2)

You could use a small table to improve speed1. Similar techniques are useful in the embedded world, for example, to invert a 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 I'm mostly referring to embedded applications where optimizers are not so aggressive and the speed difference is visible.

Komentar (0)

Print the least significant bit and shift it out on the right. Doing this until the integer becomes zero prints the binary representation without leading zeros but in reversed order. Using recursion, the order can be corrected quite easily.

#include 

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

To me, this is one of the cleanest solutions to the problem. If you like 0b prefix and a trailing new line character, I suggest wrapping the function.

Online demo

Komentar (3)

Based on @William Whyte's answer, this is a macro that provides int8,16,32 & 64 versions, reusing the INT8 macro to avoid repetition.

/* --- 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 
int main() {
    long long int flag = 1648646756487983144ll;
    printf("My Flag "
           PRINTF_BINARY_PATTERN_INT64 "\n",
           PRINTF_BYTE_TO_BINARY_INT64(flag));
    return 0;
}

This outputs:

My Flag 0001011011100001001010110111110101111000100100001111000000101000

For readability you may want to add a separator for eg:

My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
Komentar (4)

Here's a version of the function that does not suffer from reentrancy issues or limits on the size/type of the argument:

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

Note that this code would work just as well for any base between 2 and 10 if you just replace the 2's by the desired base. Usage is:

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

Where x is any integral expression.

Komentar (16)
const char* byte_to_binary( int x )
{
    static char b[sizeof(int)*8+1] = {0};
    int y;
    long long z;
    for (z=1LL>=1,y++)
    {
        b[y] = ( ((x & z) == z) ? '1' : '0');
    }

    b[y] = 0;

    return b;
}
Komentar (5)

None of the previously posted answers are exactly what I was looking for, so I wrote one. It is super simple to use %B with the printf!

    /*
     * File:   main.c
     * Author: Techplex.Engineer
     *
     * Created on February 14, 2012, 9:16 PM
     */

    #include 
    #include 
    #include 
    #include 
    #include 

    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) {
            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);
    }
Komentar (6)

Beberapa runtime mendukung "%b" meskipun itu bukan standar.

Juga lihat di sini untuk diskusi yang menarik:

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

HTH

Komentar (1)

Is there a printf converter to print in binary format?

The printf() family is only able to print in base 8, 10, and 16 using the standard specifiers directly. I suggest creating a function that converts the number to a string per code's particular needs.


To print in any base [2-36]

All other answers so far have at least one of these limitations.

  1. Use static memory for the return buffer. This limits the number of times the function may be used as an argument to printf().

  2. Allocate memory requiring the calling code to free pointers.

  3. Require the calling code to explicitly provide a suitable buffer.

  4. Call printf() directly. This obliges a new function for to fprintf(), sprintf(), vsprintf(), etc.

  5. Use a reduced integer range.

The following has none of the above limitation. It does require C99 or later and use of "%s". It uses a compound literal to provide the buffer space. It has no trouble with multiple calls in a printf().


#include 
#include 
#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 
Komentar (2)

This code should handle your needs up to 64 bits. I created 2 functions pBin & pBinFill. Both do the same thing, but pBinFill fills in the leading spaces with the fillChar. The test function generates some test data, then prints it out using the function.


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 &gt 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

Komentar (3)

Maybe a bit OT, but if you need this only for debuging to understand or retrace some binary operations you are doing, you might take a look on wcalc (a simple console calculator). With the -b options you get binary output.

e.g.

$ wcalc -b "(256 | 3) & 0xff"
 = 0b11
Komentar (1)

Tidak ada fungsi pemformatan dalam pustaka standar C untuk mengeluarkan biner seperti itu. Semua operasi format yang didukung keluarga printf adalah untuk teks yang dapat dibaca manusia.

Komentar (0)

The following recursive function might be useful:

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

}
Komentar (1)

I optimized the top solution for size and C++-ness, and got to this solution:

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;
}
Komentar (2)

Tidak ada cara standar dan portabel.

Beberapa implementasi menyediakan itoa(), tetapi tidak akan ada di sebagian besar, dan memiliki antarmuka yang agak payah. Tetapi kodenya ada di belakang tautan dan seharusnya memungkinkan Anda mengimplementasikan formatter Anda sendiri dengan cukup mudah.

Komentar (0)

I liked the code by paniq, the static buffer is a good idea. However it fails if you want multiple binary formats in a single printf() because it always returns the same pointer and overwrites the array.

Here's a C style drop-in that rotates pointer on a split buffer.

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;
}
Komentar (2)