4位十进制到16位二进制转换代码

时间:2013-03-13 07:25:10

标签: c pointers bit-manipulation

#include <stdio.h>

int main()
{
  char str[17];
  getBin(3334, str);
  printf("%s\n", str);
  return 0;
}

void getBin(int num, char *str)
{
  *(str+16) = '\0';
  int mask = 0x8000 << 1;
  while(mask >>= 1)
    *str++ = !!(mask & num) + '0';
}

我真的不明白while循环是如何运作的。有人可以用简单的语言解释它在做什么吗?感谢

2 个答案:

答案 0 :(得分:4)

是的,当然。所以0x8000 = 8 * 16 ^ 3 = 2 ^ 15。现在,如果再向左移动一次,则得到2 ^ 16。

while循环不断地掩盖所有值:

  • 2 ^ 15
  • 2 ^ 14
  • 2 ^ 13 ...

因此while循环将mask视为常规整数中2的幂的迭代器。

现在!!(mask & num)做了什么?如果掩码指示的位被翻转on,则返回1;如果是off,则返回0。

表达式!!(mask & num)返回0或1并添加到0的字符代码中,它返回01的字符代码。

例如,如果num=12mask=4,那么!!(4 & 12) = !!(100 & 1100) = !!(100)= !0 = 1。现在,如果你添加1 + '0'你会得到什么?您得到1+48=49,这是1的字符代码。

*str++ = ..将值赋给字符串中的特定位置,然后将指针递增以指向下一个字符。

问题是:str是否以null结尾?

我认为行*(str+16) = '\0';负责空终止,因为它会预防性地设置空终止字节。

所以我想这是对你上面写的代码的解释。

答案 1 :(得分:1)

void getBin(int num, char *str)

getBin()需要一个数字(num)和一个字符串来写入(str

  *(str+16) = '\0';

str的最后一个字符设置为NULL终止符

  int mask = 0x8000 << 1;

我们创建一个名为mask的变量,并将其设置为0x8000左移1,即0x10000。为什么?可能更容易在二进制文件中看到:

0x8000 16 =&gt; 1000 0000 0000 0000 2 (然后将所有东西都移到1处)
1 0000 0000 0000 0000 2 =&gt; 0x10000的<子> 16

  while(mask >>= 1)

mask大于0时,我们向右移1位,并将结果保存回mask。 (>>=表示向右移动并保存)。这意味着价值将是:

  


0x10000 16 == 1 000 0000 0000 0000 2 == 65536 10   
0x8000 16 == 1000 0000 0000 0000 2 == 32768 10   
0x4000 16 == 100 0000 0000 0000 2 == 16384 10   
0x2000 16 == 10 0000 0000 0000 2 == 8192 10   
...   
0x4 16 == 100 2 == 4 10   
0x2 16 == 10 2 == 2 10   
0x1 16 == 1 2 == 1 10

最后在每个迭代中:

    *str++ = !!(mask & num) + '0';

此代码取num中的每个数字,并将其与mask中设置的1位进行对比,然后检查结果是否为== 0,然后添加字符0的值,并将最后的ASCII“数字”存储到字符串中,然后递增字符串。

让我们一步一步地打破这一步:

mask & num // num is 3334    = 0011 0011 0011 0100
           // mask starts at = 1000 0000 0000 0000

因此,在第一次迭代中,(mask & num)的值为0

!!(x)与说(x == 0 ? 0 : 1)相同所以在第一次迭代中我们有0所以!!(0)给我们0,我们想将它存储到我们的字符串中,但我们希望它是一个ascii角色。 0的ASCII字符是0x30 16 所以我们将0x30加到0并得到0x30(或'0')然后

*str++ = '0';

我们取消引用str并存储字符0,然后我们有一个后增量移动到字符串中的下一个字符。