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

我正在运行gcc。

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

当前回答

根据@ideasman42在他的回答中的建议,这是一个提供int8、16,32和64版本的宏,重用int8宏以避免重复。

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

这个输出:

My Flag 0001011011100001001010110111110101111000100100001111000000101000

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

这将输出:

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

or

My Flag 00010110 11100001 00101011 01111101 01111000 10010000 11110000 00101000

其他回答

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

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

这个答案末尾的函数+宏的组合可以帮助你。

像这样使用它:

float float_var = 9.4;
SHOW_BITS(float_var);

变量'float_var': 01000001 00010110 01100110 01100110

请注意,它是非常通用的,可以用于几乎任何类型。 例如:

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

它将输出:

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

代码如下:

#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");
}
void binario(int num) {
  for(int i=0;i<32;i++){
    (num&(1<i))? printf("1"):
        printf("0");
  }  
  printf("\n");
}

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

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

[Edit 2022]这预计将在C的下一个版本中改变,实现“%b”。

二进制常量,如0b10101010和printf()函数族C2x的%b转换说明符


以任何基色打印[2-36]

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

使用静态内存作为返回缓冲区。这限制了函数可以作为printf()的参数使用的次数。 将需要调用代码的内存分配给释放指针。 要求调用代码显式地提供一个合适的缓冲区。 直接调用printf()。这迫使一个新函数用于fprintf(), sprintf(), vsprintf()等。 使用缩小的整数范围。

以下内容没有上述限制。它确实需要C99或更高版本,并使用“%s”。它使用复合字面值来提供缓冲空间。在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;
}

输出

1020304 5060708
1000000100000001100000100 101000001100000011100001000
100401404
A2F44
// 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');
}