Is there a printf converter to print in binary format?

前端 未结 30 2669
盖世英雄少女心
盖世英雄少女心 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:51

    Based on @ideasman42's suggestion in his 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_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;
    }
    

    This outputs:

    My Flag 0001011011100001001010110111110101111000100100001111000000101000
    

    For readability you can change :#define PRINTF_BINARY_SEPARATOR to #define PRINTF_BINARY_SEPARATOR "," or #define PRINTF_BINARY_SEPARATOR " "

    This will output:

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

    or

    My Flag 00010110 11100001 00101011 01111101 01111000 10010000 11110000 00101000
    
    0 讨论(0)
  • 2020-11-21 06:51
    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);
            }
    }
    

    should work - untested.

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

    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.

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

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

    Hacky but works for 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));
    

    For multi-byte types

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

    You need all the extra quotes unfortunately. This approach has the efficiency risks of macros (don't pass a function as the argument to BYTE_TO_BINARY) but avoids the memory issues and multiple invocations of strcat in some of the other proposals here.

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

    Next will show to you memory layout:

    #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;
    }
    
    0 讨论(0)
提交回复
热议问题