2
#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循环是如何工作的。有人可以简单地解释它在做什么吗?谢谢

4

2 回答 2

4

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

while 循环不断地对所有值进行掩码:

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

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

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

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

例如 ifnum=12mask=4then !!(4 & 12) = !!(100 & 1100) = !!(100)= !0 = 1。现在,如果你添加1 + '0'你会得到什么?你得到1+48=49哪个是1.

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

问题是:是否为str空终止?

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

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

于 2013-03-13T07:33:49.690 回答
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 => 1000 0000 0000 0000 2(然后将所有内容向左移动 1 个位置)
1 0000 0000 0000 0000 2 => 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与设置的 1 位进行“mask与”运算并检查结果是否是,== 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)所以在第一次迭代中,我们有一个0so!!(0)给我们 0,我们想将它存储到我们的字符串中,但我们希望它是一个 ascii 字符。0 的 ASCII 字符是 0x30 16所以我们将 0x30 添加到 0 并得到 0x30(或'0')然后

*str++ = '0';

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

于 2013-03-13T15:18:55.267 回答