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("\n");
while (i>=0) {
if (*temp & (1 << i)) {
printf("1");
} else {
printf("0");
}
i--;
}
temp = temp+1;
i = 7;
printf("\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" */
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 );
}
3
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;
}
2
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');
}
}
以下是 none of the above limitation . 它确实需要C99或更高版本并使用 "%s" . 它使用compound literal来提供缓冲区空间 . 在 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, 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
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;
}
char* pBinFill(long int x,char *so, char fillChar); // version with fill
char* pBin(long int x, char *so); // version without fill
#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);
}
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
30 回答
我只是想发布我的解决方案 . 它用于获取一个字节的零和一个字节,但调用此函数几次可用于更大的数据块 . 我将它用于128位或更大的结构 . 您还可以将其修改为使用size_t作为输入参数和指向要打印的数据的指针,因此它可以与大小无关 . 但它适用于我,因为它是好的 .
也许有点OT,但是如果你需要这个只是为了理解或回溯你正在做的一些二进制操作,你可以看看wcalc(一个简单的控制台计算器) . 使用-b选项可以获得二进制输出 .
例如
打印最低位并将其移出右侧 . 执行此操作直到整数变为零将打印二进制表示而不会引导零,但按相反的顺序排列 . 使用递归,订单可以很容易地纠正 .
对我来说,这是解决问题的最简洁的解决方案之一 . 如果你喜欢
0b
前缀和一个尾随的新行字符,我建议包装该函数 .Online demo
您可以使用小表来提高速度1 . 类似的技术在嵌入式世界中很有用,例如,反转一个字节:
1我主要指的是优化器不那么激进且速度差异可见的嵌入式应用程序 .
C中的一个小实用函数,用于解决位操作问题 . 这将通过字符串检查每个设置位使用掩码(1 <
使用较少的代码和资源打印任何类型的位
这种方法具有以下属性:
使用变量和文字 .
在不需要时不迭代所有位 .
仅在完成一个字节时调用printf(并非所有位都不必要) .
适用于任何类型 .
使用小而大的字节序(使用GCC #defines进行检查) .
使用不是C标准但主要定义的typeof() .
输出
我使用了 another 方法(bitprint.h)来填充一个包含所有字节(作为位串)的表,并根据输入/索引字节打印它们 . 值得一看 .
Print Binary for Any Datatype
测试
这是paniq解决方案的一小部分变体,它使用模板允许打印32位和64位整数:
并且可以像:
结果如下:
这是一个快速的黑客,以演示做你想要的技术 .
以下递归函数可能很有用:
C标准库中没有格式化函数来输出这样的二进制文件 . printf系列支持的所有格式操作都是针对人类可读的文本 .
通常,glibc中没有二进制转换说明符 .
可以将自定义转换类型添加到glibc中的printf()函数系列中 . 有关详细信息,请参阅register_printf_function . 如果它简化了应用程序代码以使其可用,则可以为自己的用途添加自定义%b转换 .
这是如何在glibc中实现自定义printf格式的example .
我的解决方案
这是一个不受重入问题影响的函数版本或对参数大小/类型的限制:
请注意,如果只是用所需的基数替换2,那么此代码对于2到10之间的任何基数都可以正常工作 . 用法是:
x
是任何整数表达式 .这是我为unsigned int做的
根据@William Whyte的回答,这是一个提供
int8
,16
,32
和64
版本的宏,重用INT8
宏来避免重复 .这输出:
为了便于阅读,您可能需要添加一个分隔符,例如:
printf()
系列只能使用标准说明符直接在基数8,10和16中打印 . 我建议创建一个函数,根据代码的特定需要将数字转换为字符串 .To print in any base [2-36]
到目前为止,所有其他答案至少具有这些限制之一 .
使用静态内存作为返回缓冲区 . 这限制了函数可以用作
printf()
的参数的次数 .分配内存,要求调用代码释放指针 .
要求调用代码显式提供合适的缓冲区 .
直接致电
printf()
. 这要求fprintf()
,sprintf()
,vsprintf()
等新功能 .使用缩小的整数范围 .
以下是 none of the above limitation . 它确实需要C99或更高版本并使用
"%s"
. 它使用compound literal来提供缓冲区空间 . 在printf()
中多次调用没有问题 .产量
Hacky但对我有用:
对于多字节类型
不幸的是,你需要所有额外的报价 . 这种方法具有宏的效率风险(不要将函数作为参数传递给
BYTE_TO_BINARY
),但是在这里的一些其他提议中避免了内存问题和strcat的多次调用 .接下来将向您展示内存布局:
没有标准和便携的方式 .
有些实现提供itoa(),但它不会出现在大多数情况下,并且它有一些有点糟糕的界面 . 但代码在链接后面,应该让你很容易实现自己的格式化程序 .
一些运行时支持“%b”,尽管这不是标准 .
另见这里有趣的讨论:
http://bytes.com/forum/thread591027.html
HTH
此代码应满足您最多64位的需求 . 我创建了2个函数pBin&pBinFill . 两者都做同样的事情,但是pBinFill用fillChar填充前导空格 . 测试功能生成一些测试数据,然后使用该功能将其打印出来 .
基于@ ideasman42在他的回答中提出的建议,这是一个提供
int8
,16
,32
和64
版本的宏,重用INT8
宏来避免重复 .这输出:
为了便于阅读,您可以更改:
#define PRINTF_BINARY_SEPARATOR
至#define PRINTF_BINARY_SEPARATOR ","
或#define PRINTF_BINARY_SEPARATOR " "
这将输出:
要么
应该工作 - 未经测试 .
我喜欢paniq的代码,静态缓冲区是个好主意 . 但是,如果您想在单个printf()中使用多个二进制格式,则会失败,因为它始终返回相同的指针并覆盖该数组 .
这是一个C风格的插件,可以在分割缓冲区上旋转指针 .
以前发布的答案都不是我想要的,所以我写了一个 . 使用
printf
%B非常简单!我优化了尺寸和C -ness的顶级解决方案,并获得了这个解决方案: