解释数据表中的十六进制并使用 C 按位左移运算符进行转换
Interpreting hex in a datasheet and converting using C bitwise left shift operators
我正在阅读数据表,它说图像的大小可以通过以下方式确定:
Image Length = len 0 + Len 1 * 100h + Len 2 * 10000h
然后在单片机上实现的代码是
L0 = Buffer[5];
L1 = Buffer[6];
L2 = Buffer[7];
image_size = L0 + (L1 << 8) + (L2 << 16);
我想知道是否有人可以解释这里发生了什么?你如何从一个转到另一个?如果相关的话,单片机是 32 位的。
100h
表示十六进制为100,十进制为256。
一个数乘以 256 相当于将其二进制表示向左移动 8。
或者更一般地说:一个数乘以 2^n 相当于将其二进制表示向左移动 n。一个数除以 2^n 相当于将它的二进制表示向右移动 n。
示例:
2 * 256 = 512
000000010 << 8 = 100000000 // << is the shift left operator
实际上是这样的:
image_size = L0 + (L1 << 8) + (L2 << 16);
可以写成:
image_size = L0 + (L1 * 0x100) + (L2 * 0x10000);
0x
前缀的意思是这个数是用十六进制而不是十进制给出的,所以我们也可以这样写:
image_size = L0 + (L1 * 256) + (L2 * 65536);
将您的 L0
、L1
和 L2
视为两位十六进制数 XX
、YY
和 ZZ
.
这里的情况是把它们放在一起组成六位十六进制数:
0xZZYYXX
因此,仅使用按位运算符将它们放在一起的一种方法是 (L2 << 16) | (L1 << 8) | L0
,我们可以这样想象:
L0 ZZ = 000000XX
L1 YY << 8 = 0000YY00
L2 ZZ << 16 = 00ZZ0000
--------
bitwise OR: 0x00ZZYYXX
但正如 Michael Walz 所解释的那样,左移 1 位相当于乘以 2,左移 8 位相当于乘以 256,即 0x100。此外,按位或与加法非常接近,只要不溢出,按位或几乎就是加法。所以我们得到与
相同的结果
(L2 * 0x10000) + (L1 * 0x100) + L0
如果您仍然看不懂,请考虑以 10 为基数而不是以 16 为基数。假设我想 "put together" 数字 12、34 和 56 得到 123456。我会这样做通过写作
(12 * 10000) + (34 * 100) + 56
注意我使用的乘数 10000 和 100 与十六进制示例中的 0x10000
和 0x100
有何惊人的相似?
(考虑这些示例的另一种方式是,当您将 L0
、L1
和 L2
放在一起时,您使用的是以 256 为基数的三位数,当我将 12、34 和 56 放在一起时,我正在以 100 为基数工作。但是如果你还没有准备好考虑以 100 为基数和以 256 为基数,别担心,你不必考虑。)
我正在阅读数据表,它说图像的大小可以通过以下方式确定:
Image Length = len 0 + Len 1 * 100h + Len 2 * 10000h
然后在单片机上实现的代码是
L0 = Buffer[5];
L1 = Buffer[6];
L2 = Buffer[7];
image_size = L0 + (L1 << 8) + (L2 << 16);
我想知道是否有人可以解释这里发生了什么?你如何从一个转到另一个?如果相关的话,单片机是 32 位的。
100h
表示十六进制为100,十进制为256。
一个数乘以 256 相当于将其二进制表示向左移动 8。
或者更一般地说:一个数乘以 2^n 相当于将其二进制表示向左移动 n。一个数除以 2^n 相当于将它的二进制表示向右移动 n。
示例:
2 * 256 = 512
000000010 << 8 = 100000000 // << is the shift left operator
实际上是这样的:
image_size = L0 + (L1 << 8) + (L2 << 16);
可以写成:
image_size = L0 + (L1 * 0x100) + (L2 * 0x10000);
0x
前缀的意思是这个数是用十六进制而不是十进制给出的,所以我们也可以这样写:
image_size = L0 + (L1 * 256) + (L2 * 65536);
将您的 L0
、L1
和 L2
视为两位十六进制数 XX
、YY
和 ZZ
.
这里的情况是把它们放在一起组成六位十六进制数:
0xZZYYXX
因此,仅使用按位运算符将它们放在一起的一种方法是 (L2 << 16) | (L1 << 8) | L0
,我们可以这样想象:
L0 ZZ = 000000XX
L1 YY << 8 = 0000YY00
L2 ZZ << 16 = 00ZZ0000
--------
bitwise OR: 0x00ZZYYXX
但正如 Michael Walz 所解释的那样,左移 1 位相当于乘以 2,左移 8 位相当于乘以 256,即 0x100。此外,按位或与加法非常接近,只要不溢出,按位或几乎就是加法。所以我们得到与
相同的结果(L2 * 0x10000) + (L1 * 0x100) + L0
如果您仍然看不懂,请考虑以 10 为基数而不是以 16 为基数。假设我想 "put together" 数字 12、34 和 56 得到 123456。我会这样做通过写作
(12 * 10000) + (34 * 100) + 56
注意我使用的乘数 10000 和 100 与十六进制示例中的 0x10000
和 0x100
有何惊人的相似?
(考虑这些示例的另一种方式是,当您将 L0
、L1
和 L2
放在一起时,您使用的是以 256 为基数的三位数,当我将 12、34 和 56 放在一起时,我正在以 100 为基数工作。但是如果你还没有准备好考虑以 100 为基数和以 256 为基数,别担心,你不必考虑。)