关于C#:是否有以二进制格式打印的printf转换器?

Is there a printf converter to print in binary format?

我可以用printf打印十六进制或八进制数字。是否有格式标记以二进制或任意基打印?

我在管理GCC。

1
2
3
4
5
6
printf("%d %x %o
"
, 10, 10, 10); //prints"10 A 12
"
print("
%b
", 10); // prints"%b
"


黑客,但对我有用:

1
2
3
4
5
6
7
8
9
10
#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')

1
printf("Leading text"BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(byte));

对于多字节类型

1
2
3
printf("m:"BYTE_TO_BINARY_PATTERN""BYTE_TO_BINARY_PATTERN"
"
,
  BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));

不幸的是,你需要所有额外的报价。这种方法具有宏的效率风险(不将函数作为参数传递给BYTE_TO_BINARY),但避免了内存问题和在某些其他方案中多次调用strcat。


打印任何数据类型的二进制文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//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("");
}

测试

1
2
3
4
5
6
7
8
9
10
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;
}


这里有一个快速的黑客演示技术做你想做的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#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
"
, strtol(b, &tmp, 2));
    }

    {
        /* byte to binary string */

        printf("%s
"
, byte_to_binary(5));
    }

    return 0;
}


glibc中通常没有二进制转换说明符。

可以向glibc中的printf()函数系列添加自定义转换类型。有关详细信息,请参阅a href="http://www.gnu.org/software/libc/manual/html_node/customizing-printf.html"rel="noreferrer">注册/a a。如果自定义的%b转换简化了应用程序代码使其可用,则可以添加该转换以供自己使用。

下面是一个如何在glibc中实现自定义printf格式的示例。


你可以用一个小桌子来提高速度1。类似的技术在嵌入式世界中很有用,例如,要反转一个字节:

1
2
3
4
5
6
7
8
9
10
11
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我主要指的是嵌入式应用程序,其中优化器没有那么激进,速度差异是可见的。


打印最低有效位并将其右移。这样做,直到整数变为零,以相反的顺序打印不带前导零的二进制表示。使用递归,可以很容易地纠正顺序。

1
2
3
4
5
6
7
8
9
#include <stdio.h>

void print_binary(int number)
{
    if (number) {
        print_binary(number >> 1);
        putc((number & 1) ? '1' : '0', stdout);
    }
}

对我来说,这是解决这个问题最干净的方法之一。如果您喜欢0b前缀和尾随的新行字符,我建议包装函数。

在线演示


根据@william whyte的回答,这是一个宏,它提供int8163264版本,重用int8宏以避免重复。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* --- 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"
"
,
           PRINTF_BYTE_TO_BINARY_INT64(flag));
    return 0;
}

此输出:

1
My Flag 0001011011100001001010110111110101111000100100001111000000101000

为了便于阅读,您可能需要添加分隔符,例如:

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


以下是函数的一个版本,它不受可重入性问题或参数大小/类型限制的影响:

1
2
3
4
5
6
7
8
9
#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;
}

请注意,如果您只是将2替换为所需的基,那么对于2到10之间的任何基,此代码都可以正常工作。用法是:

1
2
3
char tmp[FMT_BUF_SIZE];
printf("%s
"
, binary_fmt(x, tmp));

其中,x是任何积分表达式。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}


有些运行时支持"%b",尽管这不是标准。

有关有趣的讨论,请参见此处:

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

高温高压


之前发布的答案都不是我想要的,所以我写了一个。在printf中使用%b非常简单!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    /*
     * 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;
    } /* printf_arginfo_M */

    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,"
"
);
        // End of my code --------------------------------------------------------------
        len = fprintf(stream,"%s", buffer2);
        return len;
    } /* printf_output_M */

    int main(int argc, char** argv) {

        register_printf_specifier('B', printf_output_M, printf_arginfo_M);

        printf("%4B
"
, 65);

        return (EXIT_SUCCESS);
    }


此代码应能处理多达64位的需求。我创建了两个函数pbin&pbinfill。两者都做相同的事情,但是pbinfill用fillchar填充前导空格。测试函数生成一些测试数据,然后使用该函数打印出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
char* pBinFill(long int x,char *so, char fillChar); // version with fill
char* pBin(long int x, char *so);                   // version without fill
&#35;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 &gt 0);
 i++;   // point to last valid character
 sprintf(so,"%s",s+i); // stick it in the temp string string
 return so;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void test()
{
 char so[kDisplayWidth+1]; // working buffer for pBin
 long int val=1;
 do
 {
   printf("%ld =\t\t%#lx =\t\t0b%s
"
,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


C标准库中没有格式化函数来输出这样的二进制文件。printf系列支持的所有格式操作都是面向人类可读的文本的。


也许有点OT,但是如果您只需要它来进行调试,以理解或重新跟踪您正在执行的一些二进制操作,那么您可以查看wcalc(一个简单的控制台计算器)。使用-b选项可以获得二进制输出。

例如

1
2
$ wcalc -b"(256 | 3) & 0xff"
 = 0b11


Is there a printf converter to print in binary format?

printf()系列只能直接使用标准说明符以8、10和16为基数进行打印。我建议创建一个函数,根据代码的特殊需要将数字转换为字符串。

在任何基础上打印[2-36]

到目前为止,所有其他答案都至少有一个局限性。

  • 对返回缓冲区使用静态内存。这限制了函数用作printf()参数的次数。

  • 将需要调用代码的内存分配给空闲指针。

  • 要求调用代码显式提供适当的缓冲区。

  • 直接呼叫printf()。这为fprintf()sprintf()vsprintf()等赋予了新的功能。

  • 使用缩小的整数范围。

  • 以下内容不受上述限制。它需要C99或更高版本,并使用"%s"。它使用复合文字来提供缓冲区空间。在一个printf()中,多个调用没有问题。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include
    #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]){"
    <hr><P>以下递归函数可能有用:</P>[cc lang="c"]void bin(int n)
    {
        /* Step 1 */
        if (n > 1)
            bin(n/2);
        /* Step 2 */
        printf("%d", n % 2);
    }


    我优化了大小和c++的顶部解决方案,并得到了这个解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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;
    }


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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');
        }

    }


    我的解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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("
    "
    );


    使用更少的代码和资源从任何类型打印位

    这种方法具有以下特性:

    • 使用变量和文本。
    • 不需要时不重复所有位。
    • 仅当完成一个字节时才调用printf(并非所有位都不必要)。
    • 适用于任何类型。
    • 使用小的和大的endianness(使用gcc定义进行检查)。
    • 使用的typeof()不是C标准,但主要是定义的。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #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("
    "
    );
    }

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

            return 0;
    }

    产量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ ./printb
    11111111
    11111111
    00000000 11111111
    00000000 00000000 00000000 11111111
    01000100
    00000000 00000000 00000000 01000100
    01000100 00010001 11111111 00000001
    00000000 01000011

    我使用了另一种方法(bit print.h)用所有字节(作为位字符串)填充一个表,并根据输入/索引字节打印它们。值得一看。


    我喜欢paniq编写的代码,静态缓冲区是个好主意。但是,如果希望在一个printf()中使用多个二进制格式,则会失败,因为它总是返回相同的指针并覆盖数组。

    这里有一个C样式的下拉框,用于在拆分缓冲区上旋转指针。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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;
    }


    根据@ideasman42在回答中的建议,这是一个宏,它提供了int8163264版本,重用int8宏以避免重复。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    /* --- 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"
    "
    ,
               PRINTF_BYTE_TO_BINARY_INT64(flag));
        return 0;
    }

    此输出:

    1
    My Flag 0001011011100001001010110111110101111000100100001111000000101000

    为了可读性,您可以将:#define PRINTF_BINARY_SEPARATOR更改为#define PRINTF_BINARY_SEPARATOR","#define PRINTF_BINARY_SEPARATOR""

    这将输出:

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

    1
    My Flag 00010110 11100001 00101011 01111101 01111000 10010000 11110000 00101000


    没有标准的便携方式。

    有些实现提供了ITOA(),但它不会出现在大多数情况下,而且它有一个有点糟糕的接口。但是代码在链接后面,应该可以让您非常容易地实现自己的格式化程序。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /* 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" */


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #include <stdio.h>
    #include <conio.h>

    void main()
    {
        clrscr();
        printf("Welcome


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


    接下来将向您显示内存布局:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #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;
    }


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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);
            }
    }

    应该工作-未经测试。


    用途:

    1
    2
    3
    4
    5
    char buffer [33];
    itoa(value, buffer, 2);
    printf("
    binary: %s
    "
    , buffer);

    有关更多参考,请参阅如何通过printf打印二进制数。


    快速简便的解决方案:

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

    适用于任何大小的类型和有符号和无符号整数。需要"&1"来处理已签名的int,因为移位可能会进行符号扩展。

    有很多方法可以做到这一点。这是一个非常简单的方法,可以从有符号或无符号的32位类型中打印32位或n位(如果有符号,不加负号,只打印实际位),并且不返回回车。请注意,i在位移位之前是递减的:

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

    返回一个包含位的字符串以后存储或打印怎么样?您可以分配内存并返回它,用户必须释放它,或者返回静态字符串,但是如果再次调用它,或者被另一个线程调用,它将被击倒。两种方法都显示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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;
    }

    呼叫方式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // memory allocated string returned which needs to be freed
    char *pstr = int_to_bitstring_alloc(0x97e50ae6, 17);
    printf("bits = 0b%s
    "
    , 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
    "
    , pstr2);

    我只想发布我的解决方案。它用于获取一个字节的零和一个字节的零,但是很少调用这个函数可以用于更大的数据块。我将它用于128位或更大的结构。您还可以将其修改为使用大小作为输入参数和指向要打印的数据的指针,这样它就可以独立于大小。但对我来说,它是有效的,所以退出。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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);
    }


    以下是paniq解决方案的一个小变化,它使用模板来允许打印32位和64位整数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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);
    }

    可以像这样使用:

    1
    2
    3
    4
    5
    6
    7
    unsigned int value32 = 0x1e127ad;
    printf("  0x%x: %s
    "
    , value32, format_binary(value32).c_str() );

    unsigned long long value64 = 0x2e0b04ce0;
    printf("0x%llx: %s
    "
    , value64, format_binary(value64).c_str() );

    结果如下:

    1
    2
      0x1e127ad: 00000001111000010010011110101101
    0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000


    我是这样做的

    1
    2
    3
    4
    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 );
    }


    在C语言中的一个小的实用函数,在解决一个位操作问题时可以做到这一点。这将使用一个掩码(1)检查每个设置位的字符串<

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    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("
    "
    );
            while (i>=0) {
                if (*temp & (1 << i)) {
                   printf("1");
                } else {
                    printf("0");
                }
                i--;
            }
            temp = temp+1;
            i = 7;
            printf("
    "
    );
        }
    }


    使用标准库将任何整型的一个语句泛型转换为二进制字符串表示:

    1
    2
    3
    4
    5
    6
    7
    #include <bitset>
    MyIntegralType  num = 10;
    print("%s
    "
    ,
        std::bitset<sizeof(num) * 8>(num).to_string().insert(0,"0b").c_str()
    ); // prints"0b1010
    "

    或者只是:std::cout << std::bitset(num);


    另一种用二进制打印的方法是:首先转换整数。

    要以二进制方式打印6,请将6更改为110,然后打印"110"

    绕过char buf[]问题。printf()格式说明符、标志和字段(如"%08lu""%*lX"等)仍然很容易使用。不仅二进制(以2为基),该方法还可扩展到其他16个基。限制为较小的整数值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #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
    "
    , char_to_bin10(0xF1));
      // 11110001
      printf("%" PRIX64"
    "
    , uint16_to_bin16(0xF731));
      // 1111011100110001
    }


    还有一种想法是将数字转换为十六进制格式,然后将每个十六进制密码解码为四个"位"(1和0)。sprintf可以为我们做位操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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


    也许有人会发现这个解决方案很有用:

    1
    2
    3
    4
    5
    6
    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');
        }
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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("
    "
    );
    }


    1
    2
    3
    4
    5
    6
    7
    void DisplayBinary(unsigned int n)
    {
        int l = sizeof(n) * 8;
        for (int i = l - 1 ; i >= 0; i--) {
            printf("%x", (n & (1 << i)) >> i);
        }
    }


    即使对于支持%b的运行库,它似乎也只适用于整数值。

    如果你想打印二进制的浮点值,我写了一些代码,你可以在http://www.exploringbinary.com/converting-floating-point-numbers-to-binary-strings-in-c/上找到。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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 */
    }

    调用函数"拥有"字符串…

    1
    2
    3
    4
    5
    char BinaryString[17];
    ...
    PrintBinary( Value, 16, BinaryString);
    printf("yadda yadda %s yadda...
    "
    , BinaryString);

    根据CPU的不同,printBinary中的大多数操作都呈现为一个或极少数的机器指令。


    是否有以二进制格式打印的printf转换器?

    没有标准的printf格式说明符来完成"二进制"输出。这是我在需要时设计的替代方案。

    矿山为2到36之间的任何基地施工。它将这些数字扇出到递归调用的调用帧中,直到达到比基值小的数字为止。然后它向后"遍历",向前填充缓冲区,然后返回。返回值是使用的大小,如果缓冲区不够大,无法容纳字符串,则返回-1。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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;
    }

    一个重要的警告:这个函数是为与"pascal"样式的字符串一起使用而设计的,这些字符串的长度都是环绕的。因此,写入的conv_rad不会终止缓冲区。对于更一般的C使用,它可能需要一个简单的包装器来nul终止。或者打印时,只需将任务更改为putchar()s。


    下面是一个非常简单的例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    int print_char_to_binary(char ch)
    {
        int i;
        for (i=7; i>=0; i--)
            printf("%hd", ((ch & (1<<i))>>i));
        printf("
    "
    );
        return 0;
    }


    1
    2
    3
    4
    5
    6
    7
    8
    void binario(int num) {
      for(int i=0;i<32;i++){
        (num&(1<i))? printf("1"):
            printf("0");
      }  
      printf("
    "
    );
    }


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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;
    }

    请注意,不需要显式设置NUL终止符,因为buffer表示一个静态存储持续时间的对象,该对象已经填充了所有零。

    通过简单地修改num形式参数的类型,可以很容易地将其适应于unsigned long long或另一个无符号整数。

    CHAR_BIT要求包括

    下面是一个示例用法:

    1
    2
    3
    4
    5
    6
    7
    8
    int main(void)
    {
        printf(">>>%20s<<<
    "
    , toBinaryString(1));
        printf(">>>%-20s<<<
    "
    , toBinaryString(254));
        return 0;
    }

    其期望输出为:

    1
    2
    >>>                   1<<<
    >>>11111110            <<<


    使用以下功能:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void conbin(int num){  
            if(num != 0)
            {
                conbin(num >> 1);    
                if (num & 1){
                printf("1");
                }
                else{
                printf("0");
                }
            }
        }


    这可能不是很有效,但很简单。试试这个:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    tmp1 = 1;
    while(inint/tmp1 > 1) {
        tmp1 <<= 1;
    }
    do {
        printf("%d", tmp2=inint/tmp1);
        inint -= tmp1*tmp2;
    } while((tmp1 >>= 1) > 0);
    printf("");

    执行一个函数并调用它

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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]);
        }
    }