C数组中的二进制数转十进制

C binary number in array to decimal

binary_array_to_numbers() 中的循环内部发生了什么。我知道它在做什么,但我不明白它是怎么做到的。第一次看到 <<| 的用法。提前致谢。

unsigned binary_array_to_numbers(const unsigned *bits, size_t count) {
   unsigned res = 0;
   for (size_t i = 0; i < count; i++)
      res = res << 1 | bits[i];
   return res;
}

int main(void) {
   unsigned bits[] = {0, 0, 1, 0};
   unsigned received = binary_array_to_numbers(bits, sizeof(bits) / sizeof(bits[0]));
   return 0;
}

左移运算符 res << 1 将 res 移动 1 位,因此 right-most 位现在为零。然后应用 bit-wise 或运算符 | 将 right-most 位设置为 bits[i] 的值(这假设 bits 是 [=17= 的数组] 或 1 并存储 big-endian,否则你的算法将无法工作)。

假设 bits = { 1, 0, 1 }(即 5;在您的示例中它比 2 更有趣)。以下是每次迭代中发生的情况:

0.

res = res << 1 | bits[0]
res = 0x0 << 1 | 1
res = 1
res = 1 << 1 | bits[1]
res = 0x2 | 0
res = 0x2
res = 0x2 << 1 | bits[2]
res = 0x4 | 1
res = 0x5

左移运算符

左移运算符将所有位向左移动一定数量的指定位。左移运算符空出的位用0补齐。左移运算符的符号为<<.

按位或运算符

如果两个操作数的至少一个对应位为1,则按位或输出为1。在C中,按位或运算符表示为|

  • sizeof(bits) / sizeof(bits[0]) 是您想要计算 compile-time 处固定大小数组的项数时使用的常用方法。在这种情况下,编译器将默默地用 4.

    替换整个表达式
  • sizeof操作的结果整数类型是size_t类型,这是一个大的无符号整数,适合描述数组大小等。因此这种类型被用作函数的参数。

  • 数组作为 const unsigned * 传递给函数,这意味着它是 read-only 并且不会被函数修改。这是很好的做法,称为 const correctness.

  • 函数中的
  • res形成二进制bit-field.

  • 表达式 res = res << 1 | bits[i]; 中的运算符优先级 给出 [] 优于 << 优于 | 优于 =。即相当于:

    res = ( (res << 1) | bits[i] );
    
  • res << 1 将先前存储的结果向左移动一位。在循环的第一次,这是全零。移动值时,最低有效位 (LSB) 上会出现一个零。

  • 在存储在 res 中的所有内容之间进行按位或 |,无论存储在 bits[i] 中,在这种情况下恰好是 0 或 1 , 存储在 bits[i].

    的 LSB

    由于 bits[i] 的其余部分为零,因此只有这个 LSB 数据对 OR 很重要。在 res 的情况下,我们知道它的 LSB 为零。因此,在这种特定情况下,它与将 bits[i] 的内容移动到 res 的 LSB 相同,而不触及已存储在 res.

    中的任何其他位
  • 结果将是值为 0010 的二进制位域,或者如果您将十六进制 0x2.