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
.
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) 上会出现一个零。在存储在
的 LSBres
中的所有内容之间进行按位或|
,无论存储在bits[i]
中,在这种情况下恰好是 0 或 1 , 存储在bits[i]
.由于
中的任何其他位bits[i]
的其余部分为零,因此只有这个 LSB 数据对 OR 很重要。在res
的情况下,我们知道它的 LSB 为零。因此,在这种特定情况下,它与将bits[i]
的内容移动到res
的 LSB 相同,而不触及已存储在res
.结果将是值为
0010
的二进制位域,或者如果您将十六进制0x2
.