首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将float转换为长度为4的字节数组(char*数组)?

如何将float转换为长度为4的字节数组(char*数组)?
EN

Stack Overflow用户
提问于 2012-12-24 16:19:24
回答 3查看 27.2K关注 0票数 8

如何将float转换为长度为4的字节数组(char*数组)?我需要通过网络发送一些数据,tcp,并且需要将float作为字节数组发送。(我知道精确到两位小数,所以现在我在客户端乘以100,在服务器端乘以100 -基本上转换为整数,然后使用& 0xff <<操作查找字节)。但它是丑陋的,可能会随着时间的推移而失去精度。

EN

回答 3

Stack Overflow用户

发布于 2012-12-24 16:27:47

将任何类型作为字节序列读取都非常简单:

代码语言:javascript
运行
复制
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%02X\n", i, p[i]);
}

从网络流写入浮点数的工作原理与此类似,只是省略了const

总是允许将任何对象重新解释为字节序列(允许任何char-type ),这显然不违反别名。请注意,任何类型的二进制表示当然都是平台相关的,因此只有当接收方具有相同的平台时,才应将其用于序列化。

票数 16
EN

Stack Overflow用户

发布于 2012-12-24 18:49:14

您必须做的第一件事是确定网络协议中浮点数的格式。仅仅知道它是4字节并不能告诉您太多: IBM大型机、Oracle Sparc和普通PC都有4个字节的浮点数,但它们有三种不同的格式。一旦您知道了格式,根据它和您的可移植性要求,可以使用两种不同的策略:

如果协议中的格式是IEEE (最常见的情况),并且您不必移植到不是IEEE的机器(Windows和大多数Unix都是IEEE-大多数大型机都不是),那么您可以使用类型双关法将浮点数转换为uint32_t,并使用以下任一方法输出:

代码语言:javascript
运行
复制
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 );
}

对于big-endian (通常的网络顺序),或者:

代码语言:javascript
运行
复制
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,那么您将需要从浮点数中提取指数、符号和尾数,并以目标格式输出。下面的代码可以在任何机器(包括不使用IEEE的大型机)上输出IEEE big-endian,并且应该会给您一些启发:

代码语言:javascript
运行
复制
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位的无符号整数类型替换它。)

票数 6
EN

Stack Overflow用户

发布于 2014-02-20 13:23:00

只需用C++将数据覆盖在一个区域中

代码语言:javascript
运行
复制
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....  
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14018894

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档