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

时间:2020-03-06 14:30:51  来源:igfitidea点击:

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

我正在运行gcc。

printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"

解决方案

C标准库中没有格式化功能,无法像这样输出二进制文件。 printf系列支持的所有格式操作都是针对人类可读的文本。

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

另请参阅此处进行有趣的讨论:

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

高温超导

没有标准和可移植的方式。

某些实现提供了itoa(),但大多数情况下都不会用到,而且它的接口有些拙劣。但是代码位于链接的后面,应该可以让我们轻松实现自己的格式化程序。

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

可以将自定义转换类型添加到glibc中的printf()系列函数中。有关详细信息,请参见register_printf_function。如果可以简化应用程序代码的使用,则可以添加自定义%b转换供我们自己使用。

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

这是一个快速的技巧,以演示实现所需功能的技术。

#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] = '
$ wcalc -b "(256 | 3) & 0xff"
 = 0b11
'; 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; }

也许有点过时,但是如果我们仅需要进行调试以了解或者追溯正在执行的某些二进制操作,则可以看看wcalc(一个简单的控制台计算器)。使用-b选项,我们将获得二进制输出。

例如

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

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

即使对于确实支持%b的运行时库,似乎也仅适用于整数值。

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

此代码最多可以处理64位。
我创建了2个函数pBin和pBinFill。两者都做同样的事情,但是pBinFill用fillChar填充前导空格。
测试功能会生成一些测试数据,然后使用该功能将其打印出来。

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
#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));
printf("m: "BYTE_TO_BINARY_PATTERN" "BYTE_TO_BINARY_PATTERN"\n",
  BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));

对于多字节类型

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

不幸的是,我们需要所有额外的报价。这种方法具有宏的效率风险(不要将函数作为BYTE_TO_BINARY的参数传递),但是可以避免内存问题以及此处其他一些建议中strcat的多次调用。

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

应该未经测试就可以工作。

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

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

测试

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 */
}

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

调用函数"拥有"字符串...:

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

根据CPU,PrintBinary中的大多数操作都会呈现为一个或者很少的机器指令。

##代码##