# Thread: float and binary write to file

1. ## float and binary write to file

Hi
I'd like to write files with binary content (.vtk)

I need to put to file some data-points.
I know that inside file should I get (I know because I compared with some other correct written .vtk files):

3F 80 00 00 40 00 00 00

what means points = 1 , 2

but when I write myself :
Code:
```          float zma;
zma = 1;

fwrite(&zma, sizeof zma, 1, file_with_points);```
i got: >> 00 00 80 3F 00 00 00 40

Thats big and Little Endian Byte Order problem.

So I wrote function to change byte order.

Code:
```signed int LE_2_BI(signed int num)
{
liczba1, liczba2, liczba3, liczba4;

liczba1 = liczba1 << 24;

liczba2 = liczba2 << 8;

liczba3 = liczba3 >> 8;

liczba4 = liczba4 >> 24;

wynik = liczba1 | liczba2 | liczba3 | liczba4;

printf ( "num=%08x\n wynik=%08x\n", num, wynik);
return wynik;
};```
use function

Code:
```float data1;
float zma;

zma = 1;

data1 = LE_2_BI(*(int *)&zma);
fwrite(&data1, sizeof data1, 1, file_with_points);```
result 00 3F 00 47 :-(

Why ??

How can I write correct byte order into the file?

Daniel

2. Here's some code I use to convert Big Endian ints to Little Endian ints. Perhaps you can use this to spark an idea for a new approach.

Code:
```union  myunion {  // "myunion" is the type name.
char data[8] ;
int  myint ;
} ;

int fix_int(char * n, int len ) {
unsigned char temp ;
int i , j ;
myunion mydata ;

memcpy(mydata.data, n, len) ; // Copy data into my union

for (i = 0 , j = len-1 ; i < j ; ++i, --j ) {  // works for any length value

// To get little endian frm Big endian, swap this: 0X01020304 into this: 0X04030201

temp = mydata.data[i] ;
mydata.data[i] = mydata.data[j] ;
mydata.data[j] = temp ;
}

return mydata.myint ;
}```

3. Does your "wynik" output show you the correct value?

--
Mats

4. Yes.
num=3f800000
wynik=0000803f

5. I've got it:
Code:
```data1 = LE_2_BI(*(int *)&zma);

fwrite(&data1, sizeof data1, 1, file_with_points);```
This assigns a float value from an integer value.
You will need to store the int in a temporary value, then use a dereference-cast-to-float-pointer-address-of. Like you do to make the float an integer, but with float instead of int.

--
Mats

6. Another possibility:
Code:
```void bin_rev_write(const void *value, size_t size, FILE *file)
{
const unsigned char *byte = value;
for ( byte += size - 1; size--; --byte )
{
fwrite(byte, sizeof *byte, 1, file);
}
}

void foo(FILE *file)
{
float a = 1, b = 2;
bin_rev_write(&a, sizeof a, file);
bin_rev_write(&b, sizeof b, file);
}```

7. Dave,

That would indeed work. However, calling fread/fwrite many times to load and store a single float is not good for performance, compared to a few shuffle operations needed to swap byte order. [Of course, taking addresses and casting the resulting pointer is slightly outside the spec, but very few environments will have a problem with it].

--
Mats

8. Thanks for help.
However I don't understand how to use Your tip.
Piece of code would help how to convert int to float and use "dereference-cast-to-float-pointer-address-of".

Why I need to store temporary value ??

>>You will need to store the int in a temporary value, then use a dereference-cast-to-float-pointer-address-of. Like you do to make the float an integer, but with float instead of int.

9. >Why I need to store temporary value ??
You don't really. Just be sure to declare data1 as an int (or better an unsigned int):
Code:
```int data1;
float zma;

zma = 1;

data1 = LE_2_BI(*(int *)&zma);
fwrite(&data1, sizeof data1, 1, file_with_points);```

10. If you don't NEED the value as a float at all, then no, you don't need to store a temporary value. If you NEED the converted value to be a float, then you need to have an integer value at some point, then convert that by a method that makes sure that the compiler doesn't realize that the value is actually an integer, which means you have to store it in a location you can take the address of.

--
Mats