【问题标题】:Cast a 3-byte array to int32将 3 字节数组转换为 int32
【发布时间】:2021-01-29 14:20:09
【问题描述】:

快速提问,
我想将一个 3 字节带符号二进制补码数组转换为 little-endian int32
我尝试将 memcpy 的大小设置为 3 并将 +1 设置为目标地址(不要忘记将我的 int32 初始化为零)
这是我的代码:

int main(void) 
{
  // little endian 3 bytes
  __uint8_t n1[]={0,0xFF,0xDE,0x81};
  __uint8_t n2[]={0xFF,0xDE,0x81};
  
  // temp var
  __int32_t tmp1=0;
  __int32_t tmp2=0;
  
  // cast array to int
  memcpy(&tmp1,n1,4);
  memcpy((&tmp2)+1,n2,3);
  
  // printf
  printf("n1 : %d\n",tmp1);
  printf("n2 : %d\n",tmp2);
}

我得到的输出:

n1 : -2122195201
n2 : 0

我想要的输出:

n1 : -2122195201
n2 : -2122195201

我该如何解决这个问题?也许使用 union 更好?

【问题讨论】:

  • (&tmp2) 指向名为tmp2__int32_t(&tmp2)+1 指向下一个__int32_t 的位置,因为指针运算以指向类型为单位进行操作。要指向__int32_t 的第一个字节,请转换指针,与(char *) &tmp2 一样。然后,要指向下一个字节,请使用((char *) &tmp2) + 1。这就是说,像这样将三个字节复制到 32 位 int 是非常不寻常的。它通常不是一个好的程序的一部分。

标签: arrays c integer


【解决方案1】:

通过执行(&tmp2)+1,您获取tmp2 的地址,它是一个指向int32_t 的指针,并且您增加了这个指针。因此,您将 4 添加到其地址。这意味着你的 memcpy 的目标地址是tmp2 + 4 的地址。你实际上并没有修改tmp2,而是重叠了一些其他变量或内存。

这不是转换或转换数据的干净方法,但如果您真的想使用 memcpy,请执行类似(未测试)memcpy((void *)(((char *)&tmp2)+1),n2,3);

【讨论】:

  • 谢谢它的工作,我以前总是使用字节,所以我忘了这个^^
【解决方案2】:

我会避免转换值,并明确转换(这可能会被内联)

我假设您的字符数组也是 little-endian。 (否则交换索引)


static int three2four(__uint8_t three[3] )
{
int val;
val = ((unsigned)three[2] << 16) | ((unsigned)three[1] << 8) | (unsigned)three[0] ;
if (three[2] & 0x80) val |= (0xffu << 24);

return val;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 2015-10-31
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多