正在从二进制文件读取双精度字(字节顺序?)

问题描述 投票:2回答:2

我有一个二进制文件,我想从中读取一个双精度文件。

以十六进制表示,我在文件中有这8个字节(之后还有更多):

40 28 25 c8 9b 77 27 c9 40 28 98 8a 8b 80 2b d5 40 ...

这应该对应于大约10的两倍值(基于该条目的含义)。

我用过

#include<stdio.h>
#include<assert.h>

int main(int argc, char ** argv) {
   FILE * f = fopen(argv[1], "rb");
   assert(f != NULL);
   double a;
   fread(&a, sizeof(a), 1, f);
   printf("value: %f\n", a);
}

但是,打印值:-261668255698743527401808385063734961309220864.000000

很显然,字节没有正确转换为双精度。到底是怎么回事?使用ftell,我可以确认正在读取8个字节。

c io double
2个回答
3
投票

就像整数类型一样,浮点类型也受平台字节序的约束。当我在小端计算机上运行此程序时:

#include <stdio.h>
#include <stdint.h>

uint64_t byteswap64(uint64_t input) 
{
    uint64_t output = (uint64_t) input;
    output = (output & 0x00000000FFFFFFFF) << 32 | (output & 0xFFFFFFFF00000000) >> 32;
    output = (output & 0x0000FFFF0000FFFF) << 16 | (output & 0xFFFF0000FFFF0000) >> 16;
    output = (output & 0x00FF00FF00FF00FF) << 8  | (output & 0xFF00FF00FF00FF00) >> 8;
    return output;
}

int main() 
{
    uint64_t bytes = 0x402825c89b7727c9;
    double a = *(double*)&bytes;
    printf("%f\n", a);

    bytes = byteswap64(bytes);
    a = *(double*)&bytes;
    printf("%f\n", a);

    return 0;
}

然后输出是

12.073796-261668255698743530000000000000000000000000000000000.000000

这表明您的数据以小字节序格式存储在文件中,但是您的平台是大字节序。因此,您需要在读取值后执行字节交换。上面的代码显示了如何执行此操作。


2
投票

字节序是惯例。读者和作者应就使用的字节序达成一致并坚持使用。

您应该将您的数字读为int64,convert endianness,然后转换为双精度。

© www.soinside.com 2019 - 2024. All rights reserved.