Is there a printf converter to print in binary format?

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

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

    Output

    1020304 5060708
    1000000100000001100000100 101000001100000011100001000
    100401404
    A2F44
    
    0 讨论(0)
  • 2020-11-21 06:56

    Quick and easy solution:

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

    Works for any size type and for signed and unsigned ints. The '&1' is needed to handle signed ints as the shift may do sign extension.

    There are so many ways of doing this. Here's a super simple one for printing 32 bits or n bits from a signed or unsigned 32 bit type (not putting a negative if signed, just printing the actual bits) and no carriage return. Note that i is decremented before the bit shift:

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

    What about returning a string with the bits to store or print later? You either can allocate the memory and return it and the user has to free it, or else you return a static string but it will get clobbered if it's called again, or by another thread. Both methods shown:

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

    Call with:

    // 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 讨论(0)
  • 2020-11-21 06:56
    /* 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" */
    
    0 讨论(0)
  • 2020-11-21 06:57

    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 <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;
    }
    
    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;
    }
    
    int main(int argc, char** argv)
    {
        register_printf_specifier('B', printf_output_M, printf_arginfo_M);
    
        printf("%4B\n", 65);
    
        return EXIT_SUCCESS;
    }
    
    0 讨论(0)
  • 2020-11-21 06:58

    Print Binary for Any 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("");
    }
    

    Test:

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

    This code should handle your needs up to 64 bits. I created two functions: pBin and pBinFill. Both do the same thing, but pBinFill fills in the leading spaces with the fill character provided by its last argument. The test function generates some test data, then prints it out using the pBinFill function.

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