Is there a printf converter to print in binary format?

前端 未结 30 2666
盖世英雄少女心
盖世英雄少女心 2020-11-21 06:20

I can print with printf as a hex or octal number. Is there a format tag to print as binary, or arbitrary base?

I am running gcc.

printf(\"%d %x %o         


        
相关标签:
30条回答
  • 2020-11-21 06:58

    Print bits from any type using less code and resources

    This approach has as attributes:

    • Works with variables and literals.
    • Doesn't iterate all bits when not necessary.
    • Call printf only when complete a byte (not unnecessarily for all bits).
    • Works for any type.
    • Works with little and big endianness (uses GCC #defines for checking).
    • Uses typeof() that isn't C standard but is largely defined.
    #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;
    }
    

    Output

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

    I have used another approach (bitprint.h) to fill a table with all bytes (as bit strings) and print them based on the input/index byte. It's worth taking a look.

    0 讨论(0)
  • 2020-11-21 06:59

    Here is a quick hack to demonstrate the techniques for what you want.

    #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;
    }
    
    0 讨论(0)
  • 2020-11-21 07:00

    Some runtimes support "%b" although that is not a standard.

    Also see here for an interesting discussion:

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

    HTH

    0 讨论(0)
  • 2020-11-21 07:01
    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');
        }
    
    }
    
    0 讨论(0)
  • 2020-11-21 07:02

    One statement generic conversion of any integral type into the binary string representation using standard library:

    #include <bitset>
    MyIntegralType  num = 10;
    print("%s\n",
        std::bitset<sizeof(num) * 8>(num).to_string().insert(0, "0b").c_str()
    ); // prints "0b1010\n"
    

    Or just: std::cout << std::bitset<sizeof(num) * 8>(num);

    0 讨论(0)
  • 2020-11-21 07:02

    Here is a small variation of paniq's solution that uses templates to allow printing of 32 and 64 bit integers:

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

    And can be used like:

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

    Here is the result:

      0x1e127ad: 00000001111000010010011110101101
    0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000
    
    0 讨论(0)
提交回复
热议问题