【问题标题】:4byte array convert to float(c)4字节数组转换为浮点数(c)
【发布时间】:2017-03-25 15:34:57
【问题描述】:
void OPC_N2_data_read()
{
    unsigned int32 iobyte[3][4] = {0x00, };
    int32 PM_int[3] = {0x00, };
    float PM[3] = {0x00, };

    int8 i,j,k;
    int8 mask = 0x80;
    const int16 mask1 = 0x0001;
    const int16 mask0 = 0x0000;
    int8 trash_byte = 0x32;

    output_bit(ss,1);
    output_bit(PM_CLOCK_pin,0);
    delay_us (1);
    output_bit(ss,0);
    delay_us (2);  
    for( i = 0 ; i < 3 ; i ++ )
    {
      for ( j = 0 ; j < 4 ; j ++ )
      {
         for (k = 0 ; k < 8 ; k ++ )
         {
            output_bit(PM_CLOCK_pin,1); 
            iobyte[i][j] = iobyte[i][j] << 1;           
            if ( input ( PM_MISO_pin))
            {
               iobyte[i][j] |= mask1;
            }
            else
            {
               iobyte[i][j] |= mask0;
            }
            if ((trash_byte & mask) >0)
            {
                output_high(PM_MOSI_pin);
            }
            else
            {
               output_bit(PM_MOSI_pin,0);
            }            
            delay_us(1);                             
            output_bit(PM_CLOCK_pin,0);            
            delay_us(5); 
            mask = mask >>1;
         }
      }
   }
   delay_us(3);
   output_high(ss);

   for(i = 0; i<3; i++)
   {
     PM_int[i] = ((iobyte[i][0]<<24)|(iobyte[i][1]<<16)|(iobyte[i][2]<<8)|(iobyte[i][3]));
     PM[i] = *(float*)&PM_int;

   }   
   printf ("%x%x%x%x\r\n",iobyte[0][0],iobyte[0][1],iobyte[0][2],iobyte[0][3]);
   printf ("%x%x%x%x\r\n",iobyte[1][0],iobyte[1][1],iobyte[1][2],iobyte[1][3]);
   printf ("%x%x%x%x\r\n",iobyte[2][0],iobyte[2][1],iobyte[2][2],iobyte[2][3]);
   printf ("%lx,%lx,%lx\r\n", PM_int[0],PM_int[1],PM_int[2]);
   printf ("%3.5f,%3.5f,%3.5f\r\n", PM[0],PM[1],PM[2]);

}

我从一个 4 字节数组接收数据。 该数据是一个浮点值。 我通过电脑查看,我看到以下内容。

e911bd41 d867e641 8084e941 e911bd41,d867e641,8084e941 0.00000,0.00000,0.00000

将四个数据变成一个 INT 值可以正常工作。 PM_int[0],PM_int[1],PM_int[2]

但是,如果您尝试将其转换为浮点值,则只会显示 0.00000

我不知道问题出在哪里。

【问题讨论】:

  • @user694733: memcpy 也破坏了它们。唯一完全合法的类型双关语是union。尽管如此,OP 应该使用适当的(反)序列化,使用位移位和掩码到 uint32_t,然后使用 union
  • 1) 不要使用有符号整数进行位移。某些值将调用未定义的行为,对于其他值,结果是实现定义的。 2)对固定宽度类型使用标准类型,没有自制的东西!见stdint.h
  • @Olaf memcpy 根据字符类型工作。 7.24.2.1 p2:“memcpy 函数将 n 字符从 s2 指向的对象复制到 s1 指向的对象中。” 将任何数据指针类型转换为@987654336 @ 定义明确。您给出的规则适用于通过不同类型访问 same 对象。
  • @Olaf 众所周知,memcpy 从一个变量到另一个不同类型的变量是完全合法的。您断言“memcpy 在此处具有赋值运算符的语义”是不合理的。在所有其他方面memcpy 的行为就好像它通过char * 进行复制一样,这在某种程度上被函数的定义所暗示。您肯定会认识到通过char * 复制是合法的(在6.5 中强制要求这样做),建议等效的memcpy 行为不同是站不住脚的。我认为没有理由假设 memcpy 会导致通过 char 以外的任何其他类型进行访问。
  • 此外,告诉@user694733“做一些研究”是荒谬的,因为几乎所有关于该主题的完整讨论都提到使用memcpy 的合法性。例如,dbp-consulting.com/tutorials/StrictAliasing.htmlstackoverflow.com/questions/3275353/c-aliasing-rules-and-memcpy 上接受的答案; blog.regehr.org/archives/1307(“通过字符数组检查对象的表示总是可以的。这是使类似 memcpy 的函数正常工作所必需的”)。

标签: c arrays type-conversion


【解决方案1】:

查看您的源代码表明您假设接收到的iobyte[i][0]iobyte[i][3] 在以大端格式排序时应假定为浮点数:

PM_int[i] = ((iobyte[i][0]<<24)|(iobyte[i][1]<<16)|(iobyte[i][2]<<8)|(iobyte[i][3]));

但是如果你想正确转换一个 32 位的浮点值,你必须知道源 CPU 和目标 CPU 都是 big-endian 还是 little-endian。否则,必须在尝试转换值之前反转字节顺序。因此,如果您的目标具有不同的字节序,请将上面的代码替换为以下内容:

PM_int[i] = ((iobyte[i][3]<<24)|(iobyte[i][2]<<16)|(iobyte[i][1]<<8)|(iobyte[i][0]));

在您的源代码中,浮点 PM[i] 和 32 位整数 PM_int[i] 之间的转换格式错误计算出错误的结果。必须对数组PM_int[i] 的好元素执行强制转换。

PM[i] = *((float*)&(PM_int[i]));

代替:

PM[i] = *(float*)&PM_int;

接收到3个浮点值{0xe9, 0x11, 0xbd, 0x41 }, {0xd8, 0x67, 0xe6, 0x41 }, {0x80, 0x84, 0xe9, 0x41 },输出变为:

e911bd41
d867e641
8084e941
41bd11e9,41e667d8,41e98480
23.63375,28.80070,29.18970

【讨论】:

    猜你喜欢
    • 2014-02-22
    • 1970-01-01
    • 2016-08-21
    • 1970-01-01
    • 2012-11-08
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多