Reputation: 2671
I have a binary file, and I want to read a double from it.
In hex representation, I have these 8 bytes in a file (and then some more after that):
40 28 25 c8 9b 77 27 c9 40 28 98 8a 8b 80 2b d5 40 ...
This should correspond to a double value of around 10 (based on what that entry means).
I have used
#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);
}
However, that prints value: -261668255698743527401808385063734961309220864.000000
So clearly, the bytes are not converted into a double correctly. What is going on? Using ftell, I could confirm that 8 bytes are being read.
Upvotes: 4
Views: 2450
Reputation: 613461
Just like integer types, floating point types are subject to platform endianness. When I run this program on a little-endian machine:
#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;
}
Then the output is
12.073796 -261668255698743530000000000000000000000000000.000000
This shows that your data is stored in the file in little endian format, but your platform is big endian. So, you need to perform a byte swap after reading the value. The code above shows how to do that.
Upvotes: 4
Reputation: 2654
Endianness is convention. Reader and writer should agree on what endianness to use and stick to it.
You should read your number as int64, convert endianness and then cast to double.
Upvotes: 2