579

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\n", 10, 10, 10); //prints "10 A 12\n"
printf("%b\n", 10); // prints "%b\n"
Brian
  • 8,454
  • 5
  • 27
  • 30
  • 15
    Not as part of the ANSI Standard C Library -- if you're writing portable code, the safest method is to roll your own. – tomlogic Jul 08 '10 at 16:00
  • A quick Google search produced this page with some information that may be useful: http://forums.macrumors.com/archive/index.php/t-165959.html – Ian P Sep 21 '08 at 20:10
  • There isn't a format predefined for that. You need to transform it yourself to a string and then print the string. – rslite Sep 21 '08 at 20:10
  • You can not do this, as far as I know, using printf. You could, obviously, write a helper method to accomplish this, but that doesn't sound like the direction you're wanting to go. – Ian P Sep 21 '08 at 20:09
  • One statement standard and generic (for any Integral type of any length) solution of the conversion to binary string on C++: http://stackoverflow.com/a/31660310/1814353 – luart Jul 27 '15 at 18:31
  • There is no such format. But why you need this? It is too easy to implement binary print and rarely necessary - for that reason is not implemented. – i486 May 05 '16 at 14:11
  • So the expected output would be `1010` is that it? – Ciro Santilli OurBigBook.com Sep 14 '22 at 07:35

58 Answers58

376

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.

Slava Go
  • 3
  • 1
  • 3
William Whyte
  • 4,641
  • 2
  • 20
  • 17
  • 17
    And has the advantage also to be invocable multiple times in a `printf` which the ones with `static` buffers can't. – Patrick Schlüter Oct 24 '10 at 10:28
  • 6
    I've taken the liberty to change the `%d` to `%c`, because it should be even faster (`%d` has to perform digit->char conversion, while `%c` simply outputs the argument –  May 27 '16 at 15:20
  • If you are just playing with some bit twiddling exercises, you can look at the value in gddb with print /t value, which outputs in binary. – Chris Huang-Leaver Jul 20 '16 at 00:33
  • 3
    Posted an expanded version of this macro with 16, 32, 64 bit int support: http://stackoverflow.com/a/25108449/432509 – ideasman42 Jun 21 '17 at 19:57
  • 3
    Note that this approach is not stack friendly. Assuming `int` is 32-bits on system, printing single 32-bit value will require space for 32 * 4-byte values; total of 128 bytes. Which, depending on stack size, may or may not be an issue. – user694733 Oct 12 '17 at 06:47
  • @user694733 would declaring the masks (0x80, 0x40, etc) as variables above the #define make it more friendly? Or do you have another recommendation? – nmz787 Nov 29 '17 at 00:09
  • @nmz787 No, the problem is that there are 32 `'0'` or `'1'` pushed to the stack as `int`s before `printf` is entered. You can improve it by reducing the number of pushed arguments, like [this answer below does](https://stackoverflow.com/a/19885112/694733). – user694733 Nov 29 '17 at 07:41
  • 3
    its important to add parentheses around byte in the macro or you could run into problems when sending an operation BYTE_TO_BINARY(a | b) -> a | b & 0x01 != (a | b) & 0x01 – Ivan Hoffmann Jun 21 '19 at 15:21
  • CppCheck gave me a warning to clarify priority of & and ? operators. So, I guess this way is better `((byte & 0x80) ? '1' : '0')` to get each bit – Amrudesh Feb 27 '21 at 08:37
  • How does the `BYTE_TO_BINARY(byte)` definition work? It almost looks like a function. – StevieD Sep 30 '22 at 17:01
237

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;
}
ib.
  • 27,830
  • 11
  • 80
  • 100
  • 12
    Suggest `size_t i; for (i=size; i-- > 0; )` to avoid `size_t` vs. `int` mis-match. – chux - Reinstate Monica Nov 12 '13 at 19:25
  • 1
    Could someone please elaborate on the logic behind this code? – jII Jan 13 '14 at 05:39
  • 2
    Take each byte in `ptr` (outer loop); then for each bit the current byte (inner loop), mask the byte by the current bit (`1 << j`). Shift that right resulting in a byte containing 0 (`0000 0000b`) or 1 (`0000 0001b`). Print the resulting byte printf with format `%u`. HTH. – nielsbot Feb 17 '16 at 08:29
  • 1
    @chux You don't want to use `size_t i;` for a count-down loop like this because then `i` will always be `>=0`. (You could alter the loop.) – ZX9 Sep 09 '16 at 14:18
  • 2
    @ZX9 Notice that the [suggested code](http://stackoverflow.com/questions/111928/is-there-a-printf-converter-to-print-in-binary-format/3974138?noredirect=1#comment29671506_3974138) used `>` with `size_t` and not the `>=` of your comment to determine when to terminate the loop. – chux - Reinstate Monica Sep 09 '16 at 14:24
  • 4
    @ZX9 Still a useful original comment of yours as coders do need to be careful considering the edge case use of `>` and `>=` with unsigned types. `0` is an unsigned edge case and commonly occurs, unlike signed math with less common `INT_MAX/INT_MIN`. – chux - Reinstate Monica Sep 09 '16 at 17:28
  • 2
    Shouldn't the variable "byte" be "bit"? And "b" is in fact the byte array. – Jetski S-type Sep 16 '19 at 02:56
  • 2
    This is probably the best snippet of code Ive seen in my life. Seeing the address being passed to the function that is pointed by a void pointer together with passing the datatype size was in itself a university lecture for me and a moment of sheer enlightenment. – Dean P Jan 20 '21 at 19:46
  • 1
    Might be nice to print in groups of 4. To do that, you can add this line at the end of the innermost for loop: `(++k % 4 == 0) ? printf(" ") : 0;`. Don't forget to declare `k`. – Ildar Akhmetov Mar 30 '21 at 19:50
166

Here is a quick hack to demonstrate techniques to do 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;
}
EvilTeach
  • 28,120
  • 21
  • 85
  • 141
  • 3
    This is certainly less "weird" than custom writing an escape overload for printf. It's simple to understand for a developer new to the code, as well. – Furious Coder Apr 16 '09 at 23:23
  • 49
    A few changes: `strcat` is an inefficient method of adding a single char to the string on each pass of the loop. Instead, add a `char *p = b;` and replace the inner loop with `*p++ = (x & z) ? '1' : '0'`. `z` should start at 128 (2^7) instead of 256 (2^8). Consider updating to take a pointer to the buffer to use (for thread safety), similar to `inet_ntoa()`. – tomlogic Jul 08 '10 at 15:59
  • @tomlogic - I understand your viewpoint, but the question suggests that Brian may be a beginner, the use of strcat vs ()?: is more likely to be within his experience. – EvilTeach Aug 10 '10 at 12:36
  • 3
    @EvilTeach: You're using a ternary operator yourself as a parameter to `strcat()`! I agree that `strcat` is probably easier to understand than post-incrementing a dereferenced pointer for the assignment, but even beginners need to know how to properly use the standard library. Maybe using an indexed array for assignment would have been a good demonstration (and will actually work, since `b` isn't reset to all-zeros each time you call the function). – tomlogic Aug 10 '10 at 17:24
  • 3
    Random: The binary buffer char is static, and is cleared to all zeros in the assignment. This will only clear it the first time it's run, and after that it wont clear, but instead use the last value. – markwatson Aug 18 '10 at 22:10
  • I posted a shorter solution for 32-bit unsigned integers. – paniq Jul 17 '11 at 13:20
  • 9
    Also, this should document that the previous result will be invalid after calling the function again, so callers should not try to use it like this: `printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4))`. – Paŭlo Ebermann Jul 30 '11 at 23:08
  • Here's a simple macro implementation of this solution (used mainly for debugging): `#define print_binary(n) { unsigned i; for (i = 1 << 31; i > 0; i = i / 2) { (n & i)? printf("1") : printf("0"); } printf("\n"); }` – aviggiano Apr 23 '15 at 17:59
  • @tomlogic: The proper way to use `strcat` is generally "don't". Aside from very rare cases where code needs to concatenate something to a string whose length it has no way of knowing, but which is still known to have enough space after it to hold the material to be concatenated, it's almost always better to determine the string length and then use `memcpy` or direct character assignments. – supercat Jul 25 '15 at 20:00
  • 1
    @tomlogic: In a case like this, using a `for` loop which counts from 0 to 7 and writing to b[0] through b[7], and then zeroing out b[8], would be a nice clean way to go. The length of the string is known at each iteration, so `strcat` really adds nothing. – supercat Jul 25 '15 at 20:02
  • 2
    The downside is that this is not thread safe because of the static variable. – E. van Putten Oct 22 '18 at 08:42
  • Lots of downsides. markwatson is dead on that the function can only be used once. IMHO Thread safety is less of a concern in the context of the question. It's very cool how many approaches have been shown for the question. – EvilTeach Jun 04 '20 at 00:01
  • I made a gist using code from the answer and @tomlogic, and added a little extra for spacing the bytes. https://gist.github.com/dderiso/5f63a02c63045af2de1e3ffc9242cf49 . – D.Deriso Mar 17 '21 at 20:12
92

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.

DGentry
  • 16,111
  • 8
  • 50
  • 66
  • 6
    `warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]` There is a new function to do the same, though: `register_printf_specifier()`. An example of the new usage can be found here: https://codereview.stackexchange.com/q/219994/200418 – alx - recommends codidact May 09 '19 at 17:03
68

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • it works! but what is that syntax used to define bit_rep ? – 0xB00B Aug 13 '21 at 05:17
  • This code looks great. But how would you update this code to handle uint16_t, uint32_t and uint64_t? – RobK Aug 25 '21 at 02:17
  • 1
    @Robk, 4, 8 and 16 `%s`s and the same number of `bit_rep[word >> 4K & 0xF..F]` arguments should do. Although I would argue 16 string prints for a 64-bit number is probably not going to be any faster than looping 64 times and outputting 0/1. – Shahbaz Sep 19 '21 at 01:46
46

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 <stdio.h>

void print_binary(unsigned int number)
{
    if (number >> 1) {
        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

isrnick
  • 621
  • 5
  • 12
danijar
  • 32,406
  • 45
  • 166
  • 297
37

As of February 3rd, 2022, the GNU C Library been updated to version 2.35. As a result, %b is now supported to output in binary format.

printf-family functions now support the %b format for output of integers in binary, as specified in draft ISO C2X, and the %B variant of that format recommended by draft ISO C2X.

Kalcifer
  • 1,211
  • 12
  • 18
  • This is the best news I've heard this week! Just checked my Ubuntu 22.04 system; `ldd --version` reports: `ldd (Ubuntu GLIBC 2.35-0ubuntu3.1) 2.35`! The problem is that **`man 3 printf` is completely silent** on `%b` and `%B` :( –  Dec 19 '22 at 23:16
30

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 <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 may want to add a separator for eg:

My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
ideasman42
  • 42,413
  • 44
  • 197
  • 320
19

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.

ib.
  • 27,830
  • 11
  • 80
  • 100
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 1
    If you're not worried about reentrancy then you can get rid of the need for a macro or constant to define the buffer size, and the need to make that constant visible to all callers, and of course the second parameter, returning a pointer into a function-local static array. – Greg A. Woods Nov 26 '12 at 20:48
  • 9
    Yes, you *can* do that. But it's really bad design. Even if you don't have threads or reentrancy, the caller has to be aware that the static buffer is being reused, and that things like `char *a = binary_fmt(x), *b = binary_fmt(y);` will not work as expected. Forcing the caller to pass a buffer makes the storage requirement explict; the caller is of course free to use a static buffer if that's really desired, and then the reuse of the same buffer becomes explicit. Also note that, on modern PIC ABIs, static buffers usually cost more code to access than buffers on the stack. – R.. GitHub STOP HELPING ICE Nov 26 '12 at 20:55
  • 2
    reentrancy is not important in a vast number of cases. – Greg A. Woods Nov 27 '12 at 00:42
  • 2
    Also, what you're talking about w.r.t. handling multiple results sequentially is not reentrancy per se, but rather simply the fallout of using what amounts to a global object to store the result in. The function is not being re-entered. In C the proper, or at least widely used, idiom for dealing with functions that store their results in a global object is to copy those results immediately upon obtaining them. This has the major advantage that if only one result is required at a time then no additional allocation is necessary. – Greg A. Woods Nov 27 '12 at 00:51
  • 9
    That's still a bad design. It requires an extra copying step in those cases, and it's **no less expensive** than having the caller provide the buffer even in cases where copying wouldn't be required. Using static storage is just a bad idiom. – R.. GitHub STOP HELPING ICE Nov 27 '12 at 01:46
  • 4
    Having to pollute the namespace of either the preprocessor or variable symbol table with an unnecessary extra name that must be used to properly size the storage that must be allocated by _every_ caller, and forcing every caller to know this value and to allocate the necessary amount of storage, is bad design when the simpler function-local storage solution will suffice for most intents and purposes, and when a simple strdup() call covers 99% of the rest of uses. – Greg A. Woods Nov 27 '12 at 01:50
  • 6
    Here we're going to have to disagree. I can't see how adding one unobtrusive preprocessor symbol comes anywhere near the harmfulness of limiting the usage cases severely, making the interface error-prone, reserving permanent storage for the duration of the program for a temporary value, and generating worse code on most modern platforms. – R.. GitHub STOP HELPING ICE Nov 27 '12 at 01:53
  • 1
    well, we can certainly agree to disagree. For non-standardized functions the potential of limiting use cases is irrelevant since it's application specific. Whether or not use of function-local storage is more error prone than having to pedantically allocate storage for every call is, I guess, the debate -- many unix/posixy functions follow my suggested pattern so it's arguably easy for some programmers to handle. As for the cost of accessing storage, well you were not proposing use of stack storage in the first place, so you can't compare cost. – Greg A. Woods Nov 27 '12 at 02:08
  • 3
    I was proposing using stack storage. Having the caller call `malloc` for this would be hideously ugly; not only is it a huge waste of time and memory but, worst of all, you have to handle the error cases. My intent was always that most callers would pass a pointer to an array with automatic storage duration. Note that, with C99, it could even be a compound literal created at the point of the call. – R.. GitHub STOP HELPING ICE Nov 27 '12 at 02:22
  • 1
    You need to be clear that your `tmp` is an automatic variable, not a global variable, if that's what you intend; but regardless, what's important here is that there are clearly existing well-honed idioms for dealing with the common practice of using function-local static storage, and the trade-off in design terms are I think widely understood. Conversely the trade-offs in micro-performance gains for avoiding function-local static storage, especially on this scale, are largely invisible to all but the most pedantic over-optimizers. – Greg A. Woods Nov 27 '12 at 02:33
  • 7
    I don't advocate micro-optimizing without reason (i.e. measurements). But I do think performance, even if it's on the micro-gain scale, is worth mentioning when it comes as a bonus along with a fundamentally superior design. – R.. GitHub STOP HELPING ICE Nov 27 '12 at 02:39
  • @R..: If I were in a code review and saw a compound literal used in this case I'd flag it. Personally I think compound literals should have only been regarded as lvalues in cases where a compiler could render them `static const`; as it is, it becomes necessary to enclose a statement that uses a compound literal within a scoping block [e.g. to use it as part of an `if` statement or `while` loop] there's no way to extend its lifetime except by declaring an automatic variable and setting its value at the spot where the compound literal had been used (an action which would work fine if... – supercat Jul 25 '15 at 20:09
  • ...compound literals were rvalues). Even if the standard allows compound literals to be used as lvalues, the lack of any clear intention regarding lifetime would be IMHO a strong argument against it. – supercat Jul 25 '15 at 20:09
  • 1
    @supercat: Compound literals are rather useless except as lvalues. They're mainly useful where you want to pass temp storage for a result you want to throw away (think socket functions that take `socklen_t*` where `socklen_t` would suffice for most usage) or in places where you need to pass a pointer to a structure containing *inputs* to a function. I can see where you're concerned about lifetime, but it **is** well-defined and it provides the cleanest solution for formatting buffers - the API just needs to be well-documented. – R.. GitHub STOP HELPING ICE Jul 26 '15 at 17:40
  • 1
    @R..: For that sort of thing, I would think what's really needed both from a semantic *and optimization* standpoint is a qualifier to indicate that a function will not persist a pointer beyond its lifetime, or will only do so via its return value, and a rule which would allow the address of an rvalue to be taken but not stored into any persistable pointers. While I appreciate the C Standard Committee's desire to avoid "invention", the language as designed in the 1970s is insufficiently expressive to allow good optimization, and adding directives to say how pointers will be used... – supercat Jul 26 '15 at 19:02
  • ...would make code more expressive and more robust, and also allow better optimizations to be achieved without excessive compilation times [if a variable's address is only passed to functions whose prototype indicates a function it won't be persisted, a compiler wouldn't need to use whole-program optimization to keep that variable stored in registers when calling other functions]. I think the right approach would probably be to design new directives in such a fashion that code using such directives could compile on old compilers with the aid of a single `#include` directive. – supercat Jul 26 '15 at 19:09
16

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);
Robotbugs
  • 4,307
  • 3
  • 22
  • 30
  • I'm testing this and it looks like both `*int_to_bitstring_` methods do not calculate the results properly, or am I missing something? `printbits` works fine. Also, for decimals larger than 32 results of static and alloc methods begins to differ. Not much experience in C and working with bits yet. – edvard_munch May 18 '21 at 14:25
15

Is there a printf converter to print in binary format?

The printf() family is only able to print integers 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.

[Edit 2022] This is expected to change with the next version of C which implements "%b".

Binary constants such as 0b10101010, and %b conversion specifier for printf() function family C2x


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[TO_BASE_N], 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
  // size_t len = &buf[TO_BASE_N] - s;
  // memmove(buf, s, len);

  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
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 2
    This is very useful. Do you know how to use it in C++? When I compile, it generates an error "Severity Code Description Project File Line Suppression State Error C4576 a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax hello C:\my_projects\hello\hello\main.cpp 39 " – Just a learner Sep 22 '19 at 14:29
  • 1
    @Justalearner This generates a C++ because if uses a C feature _compound literal_ which is not part of C++. Perhaps post your C++ implementation that tries to do the same - even if incomplete, I am sure you will get help - as long as you show your attempt first. – chux - Reinstate Monica Sep 23 '19 at 00:12
  • 1
    This is the quality I was hopping for! Thanks for sharing – gberth Feb 16 '23 at 18:28
  • @Justalearner "This generates a C++ because if uses a C feature" should have been "This generates a C++ _error_ because if uses a C feature" – chux - Reinstate Monica Mar 01 '23 at 08:07
13
const char* byte_to_binary(int x)
{
    static char b[sizeof(int)*8+1] = {0};
    int y;
    long long z;

    for (z = 1LL<<sizeof(int)*8-1, y = 0; z > 0; z >>= 1, y++) {
        b[y] = (((x & z) == z) ? '1' : '0');
    }
    b[y] = 0;

    return b;
}
ib.
  • 27,830
  • 11
  • 80
  • 100
  • 1
    Nice solution. I would change some stuff though. I.e. going backward in the string so that input of any size could be handled properly. – Kobor42 Sep 06 '12 at 14:18
  • All those `8`s should be replaced by `CHAR_BIT`. – alk Jun 05 '16 at 14:58
  • I like that id does not use string libraries of any kind and thus can be used in an embedding setting easily – jvh Sep 30 '20 at 10:36
  • using static variables is really bad for this function. imagine `printf(byte_to_binary(1), byte_to_binary(5))`, where one call would override the string from the other call – Neuron Jan 14 '21 at 10:46
12

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;
}
ib.
  • 27,830
  • 11
  • 80
  • 100
TechplexEngineer
  • 1,836
  • 2
  • 30
  • 48
10

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
ib.
  • 27,830
  • 11
  • 80
  • 100
mrwes
  • 639
  • 1
  • 8
  • 18
8

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

Also see here for an interesting discussion:

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

HTH

John Millikin
  • 197,344
  • 39
  • 212
  • 226
rlerallut
  • 7,545
  • 5
  • 23
  • 21
7

There is no formatting function in the C standard library to output binary like that. All the format operations the printf family supports are towards human readable text.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Florian Bösch
  • 27,420
  • 11
  • 48
  • 53
7

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
quinmars
  • 11,175
  • 8
  • 32
  • 41
  • 1
    there are a few other options on this front, too... `ruby -e 'printf("%b\n", 0xabc)'`, `dc` followed by `2o` followed by `0x123p`, and so forth. – lindes Oct 13 '13 at 07:06
6

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);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kapil
  • 625
  • 12
  • 20
5

Use:

char buffer [33];
itoa(value, buffer, 2);
printf("\nbinary: %s\n", buffer);

For more ref., see How to print binary number via printf.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kapilddit
  • 1,729
  • 4
  • 26
  • 51
5

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).
  • May work with hardware that char isn't a byte (eight bits). (Tks @supercat)
  • Uses typeof() that isn't C standard but is largely defined.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <limits.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));       \
})

#define MSB_MASK 1 << (CHAR_BIT - 1)

void __printb(void *value, size_t size)
{
        unsigned char uc;
        unsigned char bits[CHAR_BIT + 1];

        bits[CHAR_BIT] = '\0';
        for_endian(size) {
                uc = ((unsigned char *) value)[i];
                memset(bits, '0', CHAR_BIT);
                for (int j = 0; uc && j < CHAR_BIT; ++j) {
                        if (uc & MSB_MASK)
                                bits[j] = '1';
                        uc <<= 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);
        printb('A');
        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 
00000000 00000000 00000000 01000001 

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.

Geyslan Gregório
  • 1,112
  • 11
  • 13
  • 1
    I've actually had the crashing issue with VLAs on my favorite embedded compiler, when using a hardware vendor's library. Some people would argue I should just use gcc or clang, but those offer no setting other than `-O0` which will refrain from making unsound optimizations (such as assuming that if a compiler would not be required to accommodate the possibility of p1 being used to access some storage within some context, and the compiler can show that p1 and p2 will be equal, it may ignore the possibility of p2 being used to access that storage). – supercat Apr 07 '21 at 15:04
5
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');
    }

}
5

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;
}
paniq
  • 1,109
  • 1
  • 11
  • 19
  • 4
    If you want to use dynamic memory (through `std::string`), you might as well get rid of the `static` array. Simplest way would be to just drop the `static` qualifier and make `b` local to the function. – Shahbaz Sep 24 '13 at 14:23
  • `((x>>z) & 0x01) + '0'` is sufficient. – Jason C Nov 03 '13 at 18:11
4

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

luart
  • 1,383
  • 1
  • 18
  • 25
4

Maybe someone will find this solution useful:

void print_binary(int number, int num_digits) {
    int digit;
    for(digit = num_digits - 1; digit >= 0; digit--) {
        printf("%c", number & (1 << digit) ? '1' : '0');
    }
}
Kresimir
  • 2,930
  • 1
  • 19
  • 13
3

No standard and portable way.

Some implementations provide itoa(), but it's not going to be in most, and it has a somewhat crummy interface. But the code is behind the link and should let you implement your own formatter pretty easily.

wnoise
  • 9,764
  • 37
  • 47
3

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
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Leo
  • 259
  • 3
  • 8
3

Yet another approach to print in binary: Convert the integer first.

To print 6 in binary, change 6 to 110, then print "110".

Bypasses char buf[] issues.
printf() format specifiers, flags, & fields like "%08lu", "%*lX" still readily usable.
Not only binary (base 2), this method expandable to other bases up to 16.
Limited to smallish integer values.

#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>

unsigned long char_to_bin10(char ch) {
  unsigned char uch = ch;
  unsigned long sum = 0;
  unsigned long power = 1;
  while (uch) {
    if (uch & 1) {
      sum += power;
      }
   power *= 10;
   uch /= 2;
  }
  return sum;
}

uint64_t uint16_to_bin16(uint16_t u) {
  uint64_t sum = 0;
  uint64_t power = 1;
  while (u) {
    if (u & 1) {
      sum += power;
      }
    power *= 16;
    u /= 2;
  }
  return sum;
}

void test(void) {
  printf("%lu\n", char_to_bin10(0xF1));
  // 11110001
  printf("%" PRIX64 "\n", uint16_to_bin16(0xF731));
  // 1111011100110001
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
3

I just want to post my solution. It's used to get zeroes and ones of one byte, but calling this function few times can be used for larger data blocks. I use it for 128 bit or larger structs. You can also modify it to use size_t as input parameter and pointer to data you want to print, so it can be size independent. But it works for me quit well as it is.

void print_binary(unsigned char c)
{
 unsigned char i1 = (1 << (sizeof(c)*8-1));
 for(; i1; i1 >>= 1)
      printf("%d",(c&i1)!=0);
}

void get_binary(unsigned char c, unsigned char bin[])
{
 unsigned char i1 = (1 << (sizeof(c)*8-1)), i2=0;
 for(; i1; i1>>=1, i2++)
      bin[i2] = ((c&i1)!=0);
}
Marko
  • 1,267
  • 1
  • 16
  • 25
3

Here's how I did it for an unsigned int

void printb(unsigned int v) {
    unsigned int i, s = 1<<((sizeof(v)<<3)-1); // s = only most significant bit at 1
    for (i = s; i; i>>=1) printf("%d", v & i || 0 );
}
andre.barata
  • 663
  • 3
  • 11
3

My solution:

long unsigned int i;
for(i = 0u; i < sizeof(integer) * CHAR_BIT; i++) {
    if(integer & LONG_MIN)
        printf("1");
    else
        printf("0");
    integer <<= 1;
}
printf("\n");
SarahGaidi
  • 51
  • 5
3
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.

Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
olli
  • 31
  • 1
3

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
Et7f3XIV
  • 562
  • 1
  • 7
  • 20
3

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;
}
Bo Persson
  • 90,663
  • 31
  • 146
  • 203
eMPee584
  • 1,945
  • 20
  • 20
  • 1
    Once `count` reaches `MAXCNT - 1`, the next increment of `count` would make it `MAXCNT` instead of zero, which will cause an access out of boundaries of the array. You should have done `count = (count + 1) % MAXCNT`. – Shahbaz Sep 24 '13 at 14:26
  • 1
    By the way, this would come as a surprise later to a developer who uses `MAXCNT + 1` calls to this function in a single `printf`. In general, if you want to give the option for more than 1 thing, make it infinite. Numbers such as 4 could only cause problem. – Shahbaz Sep 24 '13 at 14:27
2

A small utility function in C to do this while solving a bit manipulation problem. This goes over the string checking each set bit using a mask (1<

void
printStringAsBinary(char * input)
{
    char * temp = input;
    int i = 7, j =0;;
    int inputLen = strlen(input);

    /* Go over the string, check first bit..bit by bit and print 1 or 0
     **/

    for (j = 0; j < inputLen; j++) {
        printf("\n");
        while (i>=0) {
            if (*temp & (1 << i)) {
               printf("1");
            } else {
                printf("0");
            }
            i--;
        }
        temp = temp+1;
        i = 7;
        printf("\n");
    }
}
SeattleOrBayArea
  • 2,808
  • 6
  • 26
  • 38
2
#include <stdio.h>
#include <conio.h>

void main()
{
    clrscr();
    printf("Welcome\n\n\n");
    unsigned char x='A';
    char ch_array[8];
    for(int i=0; x!=0; i++)
    {
        ch_array[i] = x & 1;
        x = x >>1;
    }
    for(--i; i>=0; i--)
        printf("%d", ch_array[i]);

    getch();
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rakesh jha
  • 21
  • 2
2
void DisplayBinary(unsigned int n)
{
    int l = sizeof(n) * 8;
    for (int i = l - 1 ; i >= 0; i--) {
        printf("%x", (n & (1 << i)) >> i);
    }
}
Rassoul
  • 174
  • 16
  • I think this has been a great brainstorming session, I wish Gnu libc writers would pick the solution they like best and implement it. In 2018 I'm working at displaying binary numbers with xlib, binary as an output mode won't be obsolete as long as it's an input mode. And the width keeps changing. – Alan Corey May 28 '18 at 12:41
2
/* 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" */
Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • 4
    Paying the cost of a mallocation will hurt performance. Passing responsiblity for the destruction of the buffer to the caller is unkind. – EvilTeach Jul 17 '11 at 17:53
2

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;
}
Yola
  • 18,496
  • 11
  • 65
  • 106
1

There is also an idea to convert the number to hexadecimal format and then to decode each hexadecimal cipher to four "bits" (ones and zeros). sprintf can do bit operations for us:

const char* binary(int n) {
  static const char binnums[16][5] = { "0000","0001","0010","0011",
    "0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111" };
  static const char* hexnums = "0123456789abcdef";
  static char inbuffer[16], outbuffer[4*16];
  const char *i;
  sprintf(inbuffer,"%x",n); // hexadecimal n -> inbuffer
  for(i=inbuffer; *i!=0; ++i) { // for each hexadecimal cipher
    int d = strchr(hexnums,*i) - hexnums; // store its decimal value to d
    char* o = outbuffer+(i-inbuffer)*4; // shift four characters in outbuffer
    sprintf(o,"%s",binnums[d]); // place binary value of d there
  }
  return strchr(outbuffer,'1'); // omit leading zeros
}

puts(binary(42)); // outputs 101010
Jan Turoň
  • 31,451
  • 23
  • 125
  • 169
1
void DisplayBinary(int n)
{
    int arr[8];
    int top =-1;
    while (n)
    {
        if (n & 1)
            arr[++top] = 1;
        else
            arr[++top] = 0;

        n >>= 1;
    }
    for (int i = top ; i > -1;i--)
    {
        printf("%d",arr[i]);
    }
    printf("\n");
}
Akhil
  • 1,073
  • 1
  • 9
  • 28
1

Do a function and call it

display_binary(int n)
{
    long int arr[32];
    int arr_counter=0;
    while(n>=1)
    {
        arr[arr_counter++]=n%2;
        n/=2;
    }
    for(int i=arr_counter-1;i>=0;i--)
    {
        printf("%d",arr[i]);
    }
}
Tim Diekmann
  • 7,755
  • 11
  • 41
  • 69
Esann
  • 77
  • 5
1

My solution returns an int which can then be used in printf. It can also return the bits in big endian or little endian order.

#include <stdio.h>
#include <stdint.h>

int binary(uint8_t i,int bigEndian)
{
    int j=0,m = bigEndian ? 1 : 10000000;
    while (i)
    {
        j+=m*(i%2);
        if (bigEndian) m*=10; else m/=10;
        i >>= 1;
    }
    return j;
}

int main()
{
    char buf[]="ABCDEF";
    printf("\nbig endian = ");
    for (int i=0; i<5; i++) printf("%08d ",binary(buf[i],1));
    printf("\nwee endian = ");
    for (int i=0; i<5; i++) printf("%08d ",binary(buf[i],0));
    getchar();
    return 0;
}

Outputs

big endian = 01000001 01000010 01000011 01000100 01000101 01000110
wee endian = 10000010 01000010 11000010 00100010 10100010 01100010
NoComprende
  • 731
  • 4
  • 14
  • Very clever, not having to allocate a buffer is SO handy. (You can extend this to 16-bit values by changing binary() to accept a uint16_t, return a long, use an initial value of 1000000000000000, and then you can print the result as %ld.) – Alcamtar Nov 14 '20 at 01:45
1

The combination of functions + macro at the end of this answer can help you.

Use it like that:

float float_var = 9.4;
SHOW_BITS(float_var);

Which will output: Variable 'float_var': 01000001 00010110 01100110 01100110

Note that it is very general and can work with pretty much any type. For instance:

struct {int a; float b; double c;} struct_var = {1,1.1,1.2};
SHOW_BITS(struct_var);

Which will output:

Variable `struct_var`: 00111111 11110011 00110011 00110011 00110011 00110011 00110011 00110011 00111111 10001100 11001100 11001101 00000000 00000000 00000000 00000001

Here's the code:

#define SHOW_BITS(a) ({ \
    printf("Variable `%s`: ", #a);\
    show_bits(&a, sizeof(a));\
})

void show_uchar(unsigned char a)
{
    for(int i = 7; i >= 0; i-= 1) 
        printf("%d", ((a >> i) & 1));
}

void show_bits(void* a, size_t s)
{
    unsigned char* p = (unsigned char*) a;
    for(int i = s-1; i >= 0 ; i -= 1) {
        show_uchar(p[i]);
        printf(" ");
    }
    printf("\n");
}
Cosmo Sterin
  • 171
  • 8
1
void print_bits (uintmax_t n)
{
    for (size_t i = 8 * sizeof (int); i-- != 0;)
    {
        char c;
        if ((n & (1UL << i)) != 0)
            c = '1';
        else
            c = '0';

        printf ("%c", c);

    }
}

Not a cover-absolutely-everywhere solution but if you want something quick, and easy to understand, I'm suprised no one has proposed this solution yet.

skyfire
  • 227
  • 1
  • 6
0

It might be not very efficient but it's quite simple. Try this:

tmp1 = 1;
while(inint/tmp1 > 1) {
    tmp1 <<= 1;
}
do {
    printf("%d", tmp2=inint/tmp1);
    inint -= tmp1*tmp2;
} while((tmp1 >>= 1) > 0);
printf(" ");
Moses
  • 95
  • 1
  • 5
0

Here's is a very simple one:

int print_char_to_binary(char ch)
{
    int i;
    for (i=7; i>=0; i--)
        printf("%hd ", ((ch & (1<<i))>>i));
    printf("\n");
    return 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
hiteshradia
  • 357
  • 2
  • 9
0
void binario(int num) {
  for(int i=0;i<32;i++){
    (num&(1<i))? printf("1"):
        printf("0");
  }  
  printf("\n");
}
GutiMac
  • 2,402
  • 1
  • 20
  • 27
0

The following function returns binary representation of given unsigned integer using pointer arithmetic without leading zeros:

const char* toBinaryString(unsigned long num)
{
    static char buffer[CHAR_BIT*sizeof(num)+1];
    char* pBuffer = &buffer[sizeof(buffer)-1];

    do *--pBuffer = '0' + (num & 1);
    while (num >>= 1);
    return pBuffer;
}

Note that there is no need to explicity set NUL terminator, because buffer repesents an object with static storage duration, that is already filled with all-zeros.

This can be easily adapted to unsigned long long (or another unsigned integer) by simply modifing type of num formal parameter.

The CHAR_BIT requires <limits.h> to be included.

Here is an example usage:

int main(void)
{
    printf(">>>%20s<<<\n", toBinaryString(1));
    printf(">>>%-20s<<<\n", toBinaryString(254));
    return 0;
}

with its desired output as:

>>>                   1<<<
>>>11111110            <<<
Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137
  • 1
    Careful, that's not re-entrant. Bad things can happen if you try to use it simultaneously from two different threads, or if you save the result and call it again (the second call will clobber the first result). – Keith Thompson Jan 19 '16 at 21:45
0
void PrintBinary( int Value, int Places, char* TargetString)
{
    int Mask;

    Mask = 1 << Places;

    while( Places--) {
        Mask >>= 1; /* Preshift, because we did one too many above */
        *TargetString++ = (Value & Mask)?'1':'0';
    }
    *TargetString = 0; /* Null terminator for C string */
}

The calling function "owns" the string...:

char BinaryString[17];
...
PrintBinary( Value, 16, BinaryString);
printf( "yadda yadda %s yadda...\n", BinaryString);

Depending on your CPU, most of the operations in PrintBinary render to one or very few machine instructions.

Adam
  • 9
  • 1
0

Use below function:

void conbin(int num){  
        if(num != 0)
        {
            conbin(num >> 1);     
            if (num & 1){
            printf("1");
            }
            else{
            printf("0");
            }
        }
    }
kapilddit
  • 1,729
  • 4
  • 26
  • 51
0

This is my take on this subject.

Advantages to most other examples:

  1. Uses putchar() which is more efficient than printf() or even (although not as much) puts()
  2. Split into two parts (expected to have code inlined) which allows extra efficiency, if wanted.
  3. Is based on very fast RISC arithmetic operations (that includes not using division and multiplication)

Disadvantages to most examples:

  1. Code is not very straightforward.
  2. print_binary_size() modifies the input variable without a copy.

Note: The best outcome for this code relies on using -O1 or higher in gcc or equivalent.

Here's the code:

    inline void print_binary_sized(unsigned int number, unsigned int digits) {
        static char ZERO = '0';
        int digitsLeft = digits;
        
        do{
            putchar(ZERO + ((number >> digitsLeft) & 1));
        }while(digitsLeft--);
    }

    void print_binary(unsigned int number) {
        int digitsLeft = sizeof(number) * 8;
        
        while((~(number >> digitsLeft) & 1) && digitsLeft){
            digitsLeft--;
        }
        print_binary_sized(number, digitsLeft);
    }
brunoais
  • 6,258
  • 8
  • 39
  • 59
0
// m specifies how many of the low bits are shown.
// Replace m with sizeof(n) below for all bits and
// remove it from the parameter list if you like.

void print_binary(unsigned long n, unsigned long m) {
    static char show[3] = "01";
    unsigned long mask = 1ULL << (m-1);
    while(mask) {
        putchar(show[!!(n&mask)]); mask >>= 1;
    }
    putchar('\n');
}
jlettvin
  • 1,113
  • 7
  • 13
0

Main.c

// Based on https://stackoverflow.com/a/112956/1438550

#include <stdio.h>
#include <stdint.h>

const char *int_to_binary_str(int x, int N_bits){
    static char b[512];
    char *p = b;
    b[0] = '\0';

    for(int i=(N_bits-1); i>=0; i--){
      *p++ = (x & (1<<i)) ? '1' : '0';
      if(!(i%4)) *p++ = ' ';
    }
    return b;
}

int main() {
  for(int i=31; i>=0; i--){
    printf("0x%08X %s \n", (1<<i), int_to_binary_str((1<<i), 32));
  }
  return 0;
}

Expected behavior:

Run:
gcc -pthread -Wformat=0 -lm -o main main.c; ./main

Output:
0x80000000 1000 0000 0000 0000 0000 0000 0000 0000  
0x40000000 0100 0000 0000 0000 0000 0000 0000 0000  
0x20000000 0010 0000 0000 0000 0000 0000 0000 0000  
0x10000000 0001 0000 0000 0000 0000 0000 0000 0000  
0x08000000 0000 1000 0000 0000 0000 0000 0000 0000  
0x04000000 0000 0100 0000 0000 0000 0000 0000 0000  
0x02000000 0000 0010 0000 0000 0000 0000 0000 0000  
0x01000000 0000 0001 0000 0000 0000 0000 0000 0000  
0x00800000 0000 0000 1000 0000 0000 0000 0000 0000  
0x00400000 0000 0000 0100 0000 0000 0000 0000 0000  
0x00200000 0000 0000 0010 0000 0000 0000 0000 0000  
0x00100000 0000 0000 0001 0000 0000 0000 0000 0000  
0x00080000 0000 0000 0000 1000 0000 0000 0000 0000  
0x00040000 0000 0000 0000 0100 0000 0000 0000 0000  
0x00020000 0000 0000 0000 0010 0000 0000 0000 0000  
0x00010000 0000 0000 0000 0001 0000 0000 0000 0000  
0x00008000 0000 0000 0000 0000 1000 0000 0000 0000  
0x00004000 0000 0000 0000 0000 0100 0000 0000 0000  
0x00002000 0000 0000 0000 0000 0010 0000 0000 0000  
0x00001000 0000 0000 0000 0000 0001 0000 0000 0000  
0x00000800 0000 0000 0000 0000 0000 1000 0000 0000  
0x00000400 0000 0000 0000 0000 0000 0100 0000 0000  
0x00000200 0000 0000 0000 0000 0000 0010 0000 0000  
0x00000100 0000 0000 0000 0000 0000 0001 0000 0000  
0x00000080 0000 0000 0000 0000 0000 0000 1000 0000  
0x00000040 0000 0000 0000 0000 0000 0000 0100 0000  
0x00000020 0000 0000 0000 0000 0000 0000 0010 0000  
0x00000010 0000 0000 0000 0000 0000 0000 0001 0000  
0x00000008 0000 0000 0000 0000 0000 0000 0000 1000  
0x00000004 0000 0000 0000 0000 0000 0000 0000 0100  
0x00000002 0000 0000 0000 0000 0000 0000 0000 0010  
0x00000001 0000 0000 0000 0000 0000 0000 0000 0001 
D.Deriso
  • 4,271
  • 2
  • 21
  • 14
0

Is there a printf converter to print in binary format?

There's no standard printf format specifier to accomplish "binary" output. Here's the alternative I devised when I needed it.

Mine works for any base from 2 to 36. It fans the digits out into the calling frames of recursive invocations, until it reaches a digit smaller than the base. Then it "traverses" backwards, filling the buffer s forwards, and returning. The return value is the size used or -1 if the buffer isn't large enough to hold the string.

int conv_rad (int num, int rad, char *s, int n) {
    char *vec = "0123456789" "ABCDEFGHIJKLM" "NOPQRSTUVWXYZ";
    int off;
    if (n == 0) return 0;
    if (num < rad) { *s = vec[num]; return 1; }
    off = conv_rad(num/rad, rad, s, n);
    if ((off == n) || (off == -1)) return -1;
    s[off] = vec[num%rad];
    return off+1;
}

One big caveat: This function was designed for use with "Pascal"-style strings which carry their length around. Consequently conv_rad, as written, does not nul-terminate the buffer. For more general C uses, it will probably need a simple wrapper to nul-terminate. Or for printing, just change the assignments to putchar()s.

kisp
  • 6,402
  • 3
  • 21
  • 19
luser droog
  • 18,988
  • 3
  • 53
  • 105
0

Simple, tested, works for any unsigned integer type. No headaches.

#include <stdint.h>
#include <stdio.h>

// Prints the binary representation of any unsigned integer
// When running, pass 1 to first_call
void printf_binary(unsigned int number, int first_call)
{
        if (first_call)
        {
                printf("The binary representation of %d is [", number);
        }
        if (number >> 1)
        {
                printf_binary(number >> 1, 0);
                putc((number & 1) ? '1' : '0', stdout);
        }
        else 
        {
                putc((number & 1) ? '1' : '0', stdout);
        }
        if (first_call)
        {
                printf("]\n");
        }
}
0

As for me, I wrote some general code for this

#include<stdio.h>
void int2bin(int n, int* bin, int* bin_size, const int  bits);

int main()
{
    char ch;
    ch = 'A';
    int binary[32];
    int binary_size = 0;
    
    int2bin(1324, binary, &binary_size, 32);
    for (int i = 0; i < 32; i++)
    {
        printf("%d  ", binary[i]);
    }
    
    
    return 0;
}

void int2bin(int n, int* bin,int *bin_size,const int  bits)
{
    int i = 0;
    int temp[64];
    for (int j = 0; j < 64; j++)
    {
        temp[j] = 0;
    }
    for (int l = 0; l < bits; l++)
    {
        bin[l] = 0;
    }

    while (n > 0)
    {
        temp[i] = n % 2;
        n = n / 2;
        i++;
    }
    *bin_size = i;

    //reverse modulus values
    for (int k = 0; k < *bin_size; k++)
    {
        bin[bits-*bin_size+k] = temp[*bin_size - 1 - k];
    }
}
Blue Phoenix
  • 153
  • 11
0

You don't need to physically even enumerate the bits to generate all the bit-strings for a lookup table -

  • given an integer n := [0, 4] as input, it would enumerate all permutations of bit-strings for 2 ** n bits, in pre-sorted order, using nothing but regular expressions (regex)

    — enumerating every base4 pair of bits is n = 1, — enumerating every base16 hex is n = 2, — enumerating every byte is n = 3, since 2 ^ 3 = 8 — enumerating every short-int is n = 4

(even the 64GB ram on my laptop couldn't handle an input of 5, which would, theoretically return every single 4-byte bit string permutation, with a resulting output at least 128 GB in size … via just 5 cycles of a while() loop)


     out9:  667 B 0:00:00 [17.7MiB/s] [17.7MiB/s] [<=> ]
     1   
            2 ^ 2 ^ ( 0 ) = 
                                all permutations of 1-bit bit-strings
    4
    0, 1
    0, 1
    
     2      # gawk profile, created Wed May 17 00:50:19 2023

     3      # BEGIN rule(s)

     4      BEGIN {
     5       1      OFS = "\f\r\t"
     6       1      print " \f\t" (_ += _ ^= _ < _) " ^ " (_)\
                          " ^ ( " (+__) " ) = \fall permutations of "\
                          (_++ ^ __) "-bit bit-strings", 

                           _____ = length(___ = ____(__)), 
                          substr(___,__ = !!++_,_ *= _*_),
                          substr(___,_____  + __ - _), ""
     7      }


     8      # Functions, listed alphabetically

     9       1  function ____(__, _, ___)
    10          {
    11       1      if (+(_ = "&0&1") < (__ += ___ = "[&][01]+")) {
    12                  while (__--) {
    13                      gsub(___, _, _)
    14                  }
    15              }
    16       1      gsub(__ = "[&]", ", ", _)
    17       1      return substr(_, length(__))
    18      }
( gawk -v __="$__" -p- -be ; )  0.00s user 0.00s system 64% cpu 0.007 total

     out9:  706 B 0:00:00 [25.9MiB/s] [25.9MiB/s] [<=> ]
     1   
            2 ^ 2 ^ ( 1 ) = 
                                all permutations of 2-bit bit-strings
    14
    00, 01, 10, 11
    00, 01, 10, 11
    
     2      # gawk profile, created Wed May 17 00:50:19 2023

     8      # Functions, listed alphabetically

     9       1  function ____(__, _, ___)
    10      {
    11       1      if (+(_ = "&0&1") < (__ += ___ = "[&][01]+")) { # 1
    12       1          while (__--) {
    13       1              gsub(___, _, _)
    14                  }
    15              }
    16       1      gsub(__ = "[&]", ", ", _)
    17       1      return substr(_, length(__))
    18         }
    ( gawk -v __="$__" -p- -be ; )  0.00s user 0.00s system 63% cpu 0.007 total

     out9:  806 B 0:00:00 [28.5MiB/s] [28.5MiB/s] [<=> ]
     1   
            2 ^ 2 ^ ( 2 ) = 
                                all permutations of 4-bit bit-strings
    94
    0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111, 1000, 1001, 1010
    0101, 0110, 0111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111
    
     2      # gawk profile, created Wed May 17 00:50:19 2023

     8      # Functions, listed alphabetically

     9       1  function ____(__, _, ___)
    10          {
    11       1      if (+(_ = "&0&1") < (__ += ___ = "[&][01]+")) { # 1
    12       2          while (__--) {
    13       2              gsub(___, _, _)
    14                  }
    15              }
    16       1      gsub(__ = "[&]", ", ", _)
    17       1      return substr(_, length(__))
    18          }
( gawk -v __="$__" -p- -be ; )  0.00s user 0.00s system 63% cpu 0.006 total

     out9:  808 B 0:00:00 [18.3MiB/s] [18.3MiB/s] [<=> ]
     1   
            2 ^ 2 ^ ( 3 ) = 
                                all permutations of 8-bit bit-strings
    2558
    00000000, 00000001, 00000010, 00000011, 00000100, 00000101, 0000
    1001, 11111010, 11111011, 11111100, 11111101, 11111110, 11111111
    
     2      # gawk profile, created Wed May 17 00:50:20 2023

     8      # Functions, listed alphabetically

     9       1  function ____(__, _, ___)
    10          {
    11       1      if (+(_ = "&0&1") < (__ += ___ = "[&][01]+")) { # 1
    12       3          while (__--) {
    13       3              gsub(___, _, _)
    14                  }
    15              }
    16       1      gsub(__ = "[&]", ", ", _)
    17       1      return substr(_, length(__))
    18          }
     ( gawk -v __="$__" -p- -be ; )  0.00s user 0.00s system 62% cpu 0.007 total

     out9:  812 B 0:00:00 [22.8MiB/s] [22.8MiB/s] [<=> ]
     1   
            2 ^ 2 ^ ( 4 ) = 
                                all permutations of 16-bit bit-strings
    1179646
    0000000000000000, 0000000000000001, 0000000000000010, 0000000000
    1111111100, 1111111111111101, 1111111111111110, 1111111111111111
    
     2      # gawk profile, created Wed May 17 00:50:20 2023

     9       1  function ____(__, _, ___)
    10          {
    11       1      if (+(_ = "&0&1") < (__ += ___ = "[&][01]+")) { # 1
    12       4          while (__--) {
    13       4              gsub(___, _, _)
    14                  }
    15              }
    16       1      gsub(__ = "[&]", ", ", _)
    17       1      return substr(_, length(__))
    18          }
    ( gawk -v __="$__" -p- -be ; )  0.01s user 0.00s system 80% cpu 0.013 total

To generate them in bit-inverted manner, change the starting point from _ = "&0&1" —> _ = "&1&0" ::

    2 ^ 2 ^ ( 2 ) = 
                      all permutations of 4-bit bit-strings
    94
    1111, 1110, 1101, 1100, 1011, 1010, 1001, 1000, 0111, 0110, 0101
    1010, 1001, 1000, 0111, 0110, 0101, 0100, 0011, 0010, 0001, 0000

To generate them in a bit-reflected manner (e.g. for CRC), change both

  • _ = "&0&1" —> _ = "0&1&" , and also ___ = "[&][01]+" —> ___ = "[01]+[&]"
     out9:  200 B 0:00:00 [5.61MiB/s] [5.61MiB/s] [<=> ]
 
    2 ^ 2 ^ ( 2 ) = 
                        all permutations of 4-bit bit-strings
    94
    0000, 1000, 0100, 1100, 0010, 1010, 0110, 1110, 0001, 1001, 0101
    1010, 0110, 1110, 0001, 1001, 0101, 1101, 0011, 1011, 0111, 1111
    
  ( mawk2 -v __="$__" -- ; )  0.00s user 0.00s system 71% cpu 0.004 total
RARE Kpop Manifesto
  • 2,453
  • 3
  • 11
-1

Even for the runtime libraries that DO support %b it seems it's only for integer values.

If you want to print floating-point values in binary, I wrote some code you can find at http://www.exploringbinary.com/converting-floating-point-numbers-to-binary-strings-in-c/ .

Rick Regan
  • 3,407
  • 22
  • 28