如何将浮点转换为长度为4的字节阵列(char*的阵列)

  • 本文关键字:阵列 字节 char 转换 c++
  • 更新时间 :
  • 英文 :


如何将float转换为长度为4的字节数组(char*的数组)?我需要在网络上发送一些数据,TCP,并且需要将float作为字节数组发送。(我知道两个小数位数的精度,因此,目前我在客户端乘以100乘以100,而在100中除以100-基本上是转换为整数,然后使用& 0xff<< operations找到字节)。但这很丑陋,在时间期间可能会失去精度。

阅读任何作为字节序列类型都很简单:

float f = 0.5f;
unsigned char const * p = reinterpret_cast<unsigned char const *>(&f);
for (std::size_t i = 0; i != sizeof(float); ++i)
{
    std::printf("The byte #%zu is 0x%02Xn", i, p[i]);
}

写作从网络流的浮子上工作类似,只有您将删除const

始终允许将任何对象重新诠释为一个字节序列(任何 char -type都是允许的),并且这显然是不是是混叠的违规行为。请注意,任何类型的二进制表示当然都取决于平台,因此,如果收件人具有相同的平台,则只能将其用于序列化。

您要做的第一件事是确定漂浮在网络协议中。只是知道这是4个字节不会告诉您太多:IBM大型机,Oracle Sparc和通常PC都有四个字节浮子,但它们有三个不同格式。一旦知道格式,请根据它和您的可移植性要求,可以使用两种不同的策略:

如果协议中的格式是IEEE(最常见的情况),而且您不必便于不适合IEEE的机器(Windows和大多数Unix是IEEE&MDASH;大多数大型机),然后,您可以使用类型的PUNNING将Float转换为 uint32_t,然后输出,使用以下方法:

std::ostream&
output32BitUInt( std::ostream& dest, uint32_t value )
{
    dest.put( (value >> 24) & 0xFF );
    dest.put( (value >> 16) & 0xFF );
    dest.put( (value >>  8) & 0xFF );
    dest.put( (value      ) & 0xFF );
}

对于大端(通常的网络顺序),或:

std::ostream&
output32BitUInt( std::ostream& dest, uint32_t value )
{
    dest.put( (value      ) & 0xFF );
    dest.put( (value >>  8) & 0xFF );
    dest.put( (value >> 16) & 0xFF );
    dest.put( (value >> 24) & 0xFF );
}

对于小境(某些协议使用)。您使用哪一个将取决于为协议定义的格式。

要从float转换为uint32_t,您必须检查您的编译器。使用memcpy是唯一完全保证的方法标准;目的是使用浮子工作中的reinterpret_cast<uint32_t&>,大多数(全部?)编译器还使用union支持。

如果您还需要移植到大型机或格式是IEEE以外的其他东西,那么您需要提取指数,符号和曼蒂萨(Mantissa),并输出目标格式。类似以下的事情应该有效在任何机器上输出ieee big-endian(包括大型机)它不使用IEEE),应该给您一些想法:

oxdrstream&
oxdrstream::operator<<(
    float               source )
{
    BytePutter          dest( *this ) ;
    bool                isNeg = source < 0 ;
    if ( isNeg ) {
        source = - source ;
    }
    int                 exp ;
    if ( source == 0.0 ) {
        exp = 0 ;
    } else {
        source = ldexp( frexp( source, &exp ), 24 ) ;
        exp += 126 ;
    }
    uint32_t               mant = source ;
    dest.put( (isNeg ? 0x80 : 0x00) | exp >> 1 ) ;
    dest.put( ((exp << 7) & 0x80) | ((mant >> 16) & 0x7F) ) ;
    dest.put( mant >> 8 ) ;
    dest.put( mant      ) ;
    return *this ;
}

BytePutter是一个简单的课程,可以照顾通常样板并进行错误检查。)当然,各种如果输出,输出的操作将有所不同格式不是IEEE,但这应该显示基本原理。(如果您需要一些更奇特的大型机的便携性,不支持uint32_t,您可以用任何大于23位的未签名积分类型。)

在C

中叠加一个区域的数据
union dataUnion {  
    float f;  
    char fBuff[sizeof(float)];  
}  
// to use:  
dataUnion myUnion;  
//  
myUnion.f = 3.24;  
for(int i=0;i<sizeof(float);i++)  
    fputc(myUnion.fbuff[i],fp); // or what ever stream output....  

最新更新