我可以使用printf
将数字以十六进制或八进制形式打印出来。是否有格式标签可以打印成二进制或其他任意进制?
我正在运行gcc。
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
printf("%b\n", 10); // prints "%b\n"
是否有一个 printf 转换器以二进制格式打印?
printf()
系列只能使用标准的转换符直接打印8进制、10进制和16进制的整数。我建议创建一个函数,根据代码的特定需求将数字转换为字符串。
[编辑 2022] 下一个C语言版本将实现 "%b"
,支持二进制常量如0b10101010,以及printf()
函数族的%b转换说明符。
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
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;
}
8
应该被替换为 CHAR_BIT
。 - alkprintf(byte_to_binary(1), byte_to_binary(5))
,其中一个调用会覆盖另一个调用的字符串。 - Neuron之前发布的回答都不是我所寻找的,因此我自己写了一个。使用printf
非常简单,只需要使用%B
即可!
/*
* 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;
}
char* buffer = (char*) malloc(sizeof(char) * 50);
- Janus Troelsenchar *buffer = malloc(sizeof(*buffer) * 50);
。 - Shahbaz这段代码应该能够处理你的需求,最多可以达到64位。
我创建了两个函数:pBin
和pBinFill
。它们都做同样的事情,但是pBinFill
会使用其最后一个参数提供的填充字符来填充前导空格。
测试函数生成一些测试数据,然后使用pBinFill
函数打印出来。
#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);
}
输出:
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系列函数支持的所有格式化操作都是用于生成人类可读的文本。
也许有些偏题,但如果你只需要用于调试以理解或重现一些二进制操作,您可以尝试使用wcalc(一个简单的控制台计算器)。 使用-b选项,您可以获得二进制输出。
例如:
$ wcalc -b "(256 | 3) & 0xff" = 0b11
ruby -e 'printf("%b\n", 0xabc)'
、dc
后跟 2o
再跟上 0x123p
等等。 - lindesvoid bin(int n)
{
/* Step 1 */
if (n > 1)
bin(n/2);
/* Step 2 */
printf("%d", n % 2);
}
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;
}
std::string
),那么最好摆脱静态数组。最简单的方法就是去掉static
限定符,并将b
设置为函数本地变量。 - Shahbaz((x>>z) & 0x01) + '0'
是足够的。 - Jason Cvoid
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');
}
}
1010
,对吗? - Ciro Santilli OurBigBook.com