Is there a printf converter to print in binary format?

前端 未结 30 2698
盖世英雄少女心
盖世英雄少女心 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 
    #include 
    #include 
    
    #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.

提交回复
热议问题