TeslaFan:
//Converting a float to 4 bytes:
.
.
.
Everything is made of bytes. There is nothing stopping you from taking them apart and putting them back together through pointer and memory manipulation.
I’m with you up to here.
However…
TeslaFan:
With a float, byte ordering is the same in all systems.
Not true. I have an application running on an Intel IXP420 arm-xscale processor. Integer variables and floating point variables are all stored big-endian. On my i386 workstations and on my ATmega boards, they are all stored little-endian. See Footnote.
TeslaFan:
But with 16 and 32 bit ints, Intel PCs and Atmel microcontrollers store the bytes in a different order.
No they are not. With avr-gcc (Arduino’s compiler), integer and floating point variables are all stored little-endian (same as on my i386 Windows and Linux workstations).
TeslaFan:
You have to swap the bytes around if you use this method to send ints or longs.
You have to swap bytes if (and only if) the transmitter and receiver are different-endian. Period. Full Stop.
Higher level network protocols usually (almost always, I think) specify that binary bytes (octets) of multi-byte numerical quantities be sent in big-endian order. Compiler vendors usually supply byte-swapping functions or macros that convert machine-endian integers to network-endian (i.e. big-endian) representation. By using vendor-supplied functions like htons, htonl, ntohs, ntohl, etc. the program source can be compiled on either type of system without modification. These create no overhead for big-endian systems but actually require that the processor do some work little-endian systems.
Regards,
Dave
Footnote:
Arduino sketch:
void setup()
{
Serial.begin(9600);
uint16_t x = 0x1234;
float z = 1.125e4;
unsigned i;
unsigned char *chpt;
Serial.print("Here's the 16-bit integer : 0x");
Serial.println(x, HEX);
chpt = (unsigned char *)&x;
Serial.print("Here are the bytes in memory order: ");
for (i = 0; i < sizeof(x); i++) {
Serial.print("0x");
Serial.print(chpt[i],HEX);
Serial.print(" ");
}
Serial.println();Serial.println();
chpt = (unsigned char *)&z;
Serial.print("Here's the float : ");Serial.println(z);
Serial.print("Here are the bytes in memory order: ");
for (i = 0; i < sizeof(z); i++) {
Serial.print("0x");
Serial.print(chpt[i],HEX);
Serial.print(" ");
}
Serial.println();
}
void loop(){}
Output from Duemilanove:
[color=blue]Here's the 16-bit integer : 0x1234
Here are the bytes in memory order: 0x34 0x12
Here's the float : 11250.00
Here are the bytes in memory order: 0x0 0xC8 0x2F 0x46
[/color]
The integer is obviously stored least-significant byte first, right?
Then…
Look at the bytes of the floating point number and you can see that the float is stored least-significant byte first.
(You can work it out using a reference like: Floating Point on Wikipedia.)
Equivalent standard C program compiled with GNU gcc on my Linux workstation:
#include <stdio.h>
#include <stdint.h>
int main()
{
uint16_t x = 0x1234;
float z = 1.125e4;
unsigned i;
unsigned char *chpt;
chpt = (unsigned char *)&x;
printf("Here's the 16-bit integer : 0x%02x\n", x);
printf("Here are the bytes in memory order: ");
for (i = 0; i < sizeof(x); i++) {
printf("0x%02x ", chpt[i]);
}
printf("\n");
printf("Here's the float : %.2f\n", z);
chpt = (unsigned char *)&z;
printf("Here are the bites in memory order: ");
for (i = 0; i < sizeof(z); i++) {
printf("0x%02x ", chpt[i]);
}
printf("\n");
return 0;
}
Output:
[color=blue]Here's the 16-bit integer : 0x1234
Here are the bytes in memory order: 0x34 0x12
Here's the float : 11250.00
Here are the bites in memory order: 0x00 0xc8 0x2f 0x46
[/color]
Same results as with Arduino: Little-endian all the way.
Then:
When I cross-compiled the same C program with arm-linux-gcc for the xscale and ran the result on the target system, here’s the output:
[color=blue]Here's the 16-bit integer : 0x1234
Here are the bytes in memory order: 0x12 0x34
Here's the float : 11250.00
Here are the bites in memory order: 0x46 0x2f 0xc8 0x00[/color]
Big-endian all the way!
Final note (I promise. Really)
I don’t remember ever having to send binary floating point numbers from workstation to arm-xscale system (or anything else to anything else either), but if I ever need to, I might check this out: Floating-point and Endianness on Wikipedia