我可以用printf打印十六进制或八进制数字。是否有格式标签打印为二进制或任意基数?
我正在运行gcc。
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
printf("%b\n", 10); // prints "%b\n"
我可以用printf打印十六进制或八进制数字。是否有格式标签打印为二进制或任意基数?
我正在运行gcc。
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
printf("%b\n", 10); // prints "%b\n"
当前回答
/* 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" */
其他回答
一些运行时支持“%b”,尽管这不是标准。
也可以在这里看到一个有趣的讨论:
http://bytes.com/forum/thread591027.html
HTH
也许有人会发现这个解决方案很有用:
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');
}
}
使用更少的代码和资源打印任何类型的位
这种方法有以下属性:
使用变量和字面量。 没有必要时不迭代所有位。 只在完成一个字节时调用printf(不必对所有位都调用)。 适用于任何类型。 使用大小字节序(使用GCC #定义进行检查)。 可以与char不是字节(8位)的硬件一起工作。(谢谢大家@supercat) 使用typeof(),它不是C标准的,但在很大程度上是定义的。
#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;
}
输出
$ ./printb
11111111
11111111
00000000 11111111
00000000 00000000 00000000 11111111
01000100
00000000 00000000 00000000 01000100
01000100 00010001 11111111 00000001
00000000 01000011
00000000 00000000 00000000 01000001
我使用了另一种方法(bitprint.h)用所有字节(作为位字符串)填充一个表,并根据输入/索引字节打印它们。值得一看。
下面是一个不受重入性问题或参数大小/类型限制的函数版本:
#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到10之间的任何底数,只要将2替换为所需的底数。用法是:
char tmp[FMT_BUF_SIZE];
printf("%s\n", binary_fmt(x, tmp));
其中x是任意的积分表达式。
下面是paniq解决方案的一个小变种,它使用模板来允许打印32位和64位整数:
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);
}
并且可以这样使用:
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() );
结果如下:
0x1e127ad: 00000001111000010010011110101101
0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000