gpt4 book ai didi

将 32 位数字转换为四个 8 位数字

转载 作者:行者123 更新时间:2023-12-04 00:18:05 36 4
gpt4 key购买 nike

我正在尝试将来自设备的输入(始终为 1 到 600000 之间的整数)转换为四个 8 位整数。
例如,
如果输入是32700,我要188 127 00 00 .
我通过使用实现了这一点:

32700 % 256 
32700 / 256
以上工作到 32700。从 32800 开始,我开始得到不正确的转换。
我对此完全陌生,并希望得到一些帮助以了解如何正确完成此操作。

最佳答案

主要编辑以下澄清:
鉴于有人已经提到了 shift-and-mask 方法(不可否认,这是正确的方法),我将给出另一种方法,迂腐,不可移植,依赖于机器,并且可能表现出未定义的行为。尽管如此,IMO 还是一个很好的学习练习。
由于各种原因,您的计算机将整数表示为一组 8 位值(称为字节);请注意,虽然非常普遍,但情况并非总是如此(请参阅 CHAR_BIT )。出于这个原因,使用多于 8 位表示的值使用多个字节(因此使用多个位的值是 8 的倍数)。对于 32 位值,您使用 4 个字节,并且在内存中,这些字节始终紧随其后。
我们称指针为包含另一个值在内存中的地址的值。在这种情况下,字节被定义为指针可以引用的最小(就位计数而言)值。例如,您的 32 位值,覆盖 4 个字节,将有 4 个“可寻址”单元(每个字节一个),其地址定义为这些地址中的第一个:

|==================|
| MEMORY | ADDRESS |
|========|=========|
| ... | x-1 | <== Pointer to byte before
|--------|---------|
| BYTE 0 | x | <== Pointer to first byte (also pointer to 32-bit value)
|--------|---------|
| BYTE 1 | x+1 | <== Pointer to second byte
|--------|---------|
| BYTE 2 | x+2 | <== Pointer to third byte
|--------|---------|
| BYTE 3 | x+3 | <== Pointer to fourth byte
|--------|---------|
| ... | x+4 | <== Pointer to byte after
|===================
因此,您想要做的(将 32 位字拆分为 8 位字)已经由您的计算机完成,因为它是由其处理器和/或内存架构强加给它的。为了获得这种几乎巧合的好处,我们将找到您的 32 位值的存储位置并逐字节读取其内存(而不是一次 32 位)。
由于所有严肃的 SO 答案似乎都是这样做的,让我引用标准 (ISO/IEC 9899:2018, 6.2.5-20) 来定义我需要的最后一件事(强调我的):

Any number of derived types can be constructed from the object and function types, as follows:

  • An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. [...] Array types are characterized by their element type and by the number of elements in the array. [...]
  • [...]

因此,由于数组中的元素被定义为连续的,内存中的 32 位值,在具有 8 位字节的机器上,在其机器表示中,实际上只不过是一个 4 字节的数组!
给定一个 32 位有符号值:
int32_t value;
它的地址由 &value 给出.同时,一个 4 个 8 位字节的数组可以表示为:
uint8_t arr[4];
请注意,我使用了 unsigned 变体,因为这些字节本身并不真正代表一个数字,因此将它们解释为“有符号”是没有意义的。现在,一个指向 4 数组的指针- uint8_t定义为:
uint8_t (*ptr)[4];
如果我将 32 位值的地址分配给这样的数组,我将能够单独索引每个字节,这意味着我将直接读取字节,避免任何讨厌的移位和屏蔽操作!
uint8_t (*bytes)[4] = (void *) &value;
我需要转换指针(“ (void *)”),因为我无法忍受那个提示的编译器 &value的类型是“pointer-to- int32_t”,而我将它分配给“pointer-to-array-of-4- uint8_t”,并且这种类型不匹配被编译器捕获并迂腐警告按标准;这是第一个警告,我们正在做的事情并不理想!
最后,我们可以通过索引直接从内存中读取每个字节来单独访问每个字节: (*bytes)[n]阅读 n value的第 - 个字节!
总而言之,给定一个 send_can(uint8_t)功能:
for (size_t i = 0; i < sizeof(*bytes); i++)
send_can((*bytes)[i]);
并且,为了测试目的,我们定义:
void send_can(uint8_t b)
{
printf("%hhu\n", b);
}
在我的机器上打印 value32700 :
188
127
0
0
最后,这显示了该方法依赖于平台的另一个原因:存储 32 位字的字节的顺序并不总是您从二进制表示的理论讨论中所期望的,即:
  • 字节 0 包含位 31-24
  • 字节 1 包含位 23-16
  • 字节 2 包含位 15-8
  • 字节 3 包含位 7-0

  • 实际上,AFAIK,C 语言允许对这 4 个字节进行排序的 24 种可能性中的任何一种(这称为字节序)。同时,移动和掩蔽将始终为您提供 n -th“逻辑”字节。

    关于将 32 位数字转换为四个 8 位数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62607049/

    36 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com