get single bytes from double

Hi

i need to write values to the EEPROM of the arduino, but therefore i need to split up values to single bytes.
e.g. i have a value with 0x01D4629D as hex representation (30696093 in decimal), and I store this value as double.

now i want to split it up to 0x01 0xD4 0x62 0x9D to store each value in an eeprom address.

How can i do this? i've searched the internet to find a solution, but the only answer that seems to be relevant is this:

int newByte = (hexCode >> (1 * 8)) & 0xFF;

I tried this, but it gave me an error:

sketch_jun21a:32: error: invalid operands of types 'double' and 'int' to binary 'operator>>'

I want to thank you in advance for your help :slight_smile:
Also, if there are any mistakes in my description of bytes, double etc, please correct me, because I'm not completely sure everything is correct, thanks.
Nick

Create a "byte" pointer.
With a cast, assign it the address of your float.
Address the four bytes comprising the float using the pointer.
Quick, and very dirty.

byte newByte = (((long)hexCode) >>(i *  8)) & 0xFF; I think, compiler will do the right things for you, after its spotted shift by 8, so manipulation will go on bytes scale, not bites.

AWOL:
Quick, and very dirty.

Sometimes that's all you need.

AWOL:
Create a "byte" pointer.
With a cast, assign it the address of your float.
Address the four bytes comprising the float using the pointer.
Quick, and very dirty.

could you please give an example? i'm not used to bit/byte manipulations xs thanks

byte* pointer = (byte*)&myFloat;

There are no bit manipulations necessary.

but then how can i select each different byte from it? i really don't get how this works..

and that myFloat, is that the double you mean? i don't use any float

On an Arduino, a float and a double are the same.

how can i select each different byte from it?

byte* pointer = (byte*)&myFloat;
byte first = pointer[0];
byte second = pointer [1];

etc.

AWOL:
On an Arduino, a float and a double are the same.

oh, that's why it shows 30696093.00000000000 in the serial monitor.. that's clear now.
hmm, ok thanks, i'm gonna try it out

this should work right?

  byte* pointer = (byte*)&hexCode;
  for (int i=0; i<sizeof(pointer); i++)
  {
    Serial.print(pointer[i], HEX);
    Serial.print("\t");
  }
  Serial.println("");

it gives me weird results, this is when i try to 'decode' 0x01D4629D:

4E 31

where does this come from?

oh, that's why it shows 30696093.00000000000 in

No, that's probably because you typed Serial.print (myFloat, DEC);
Asking for ten decimal places of a float is...optimistic.

for (int i=0; i<sizeof(pointer); i++)

sizeof(pointer) is 2, so only two digits are printed.
sizeof (hexcode) might work.

this is the whole decode code:

void decode (double hexCode)
{
  byte* pointer = (byte*)&hexCode;
  
  if (hexCode != 0x0)
  {
    Serial.print(hexCode, HEX);
    Serial.print(" = ");
    for (int i=0; i<sizeof(hexCode); i++)
    {
      Serial.print(pointer[i], HEX);
      Serial.print("\t");
    }
  }
}

and this is the serial monitor output:

30696092.0000000000000000 = 4E 31 EA 4B

there are some strange things going on here:

  1. the Serial.print(hexCode, HEX); prints it in decimal
  2. between 31 and EA there are twe tabspaces, which means an empty listitem is present in pointer[2]? or is this something else
  3. It does definitely not output what i want it to do, but how could i possibly solve it?

It does definitely not output what i want it to do, but how could i possibly solve it?

Well, for a start, you could tell us what you want it to do, and how what it is doing differs from that.

Stop and think - tell us what you WANT to do, not how you think you should do it.

  1. the Serial.print(hexCode, HEX); prints it in decimal

"4E 31 EA 4B" are clearly NOT decimal.

With this pointer approach, how do I know which order data stored in memory , MSByte first or LSByte?
Shift >> 8 looks easier and portable (IMHO).

Shift >> 8 looks easier and portable

Agreed - I said my approach was quick and dirty.
However, for a "double" datatype, neither is truly portable, because of the different width of "double" on different platforms.

Steen:

  1. the Serial.print(hexCode, HEX); prints it in decimal

As per the documentation: Serial.println() - Arduino Reference
format: specifies the number base (for integral data types) or number of decimal places (for floating point types)

So that line of code is only telling it to print hexCode out to however many decimal places HEX converts to. print/ln does not support outputing floats/doubles in HEX format, which is why you need to resort to some explicit conversion yourself.

Steen:
2. between 31 and EA there are twe tabspaces, which means an empty listitem is present in pointer[2]? or is this something else

I only see a single tabspace between items. Most easily observed if you change the line to something like: Serial.print("-\t-");
But it also copies/pastes into a spreadsheet properly delimited as well. So, why do you believe it's outputing two tabs?

Steen:
3. It does definitely not output what i want it to do, but how could i possibly solve it?

As AWOL said, what exactly do you want it to do?

AWOL:
Stop and think - tell us what you WANT to do, not how you think you should do it.

As i told in the first post, i have a value, e.g. 0x01D4629D, and i want to split this up in 0x01, 0xD4, 0x62 and 0x9D because i want to store them in eeprom memory.

the output is 4E 31 EA 4B, which is not 01 D4 62 9D. that's what i mean with different.

  1. the Serial.print(hexCode, HEX); prints it in decimal

"4E 31 EA 4B" are clearly NOT decimal.

i meant the 30696092.0000000000000000, which is decimal, while i use HEX to print, 4E etc are clearly hex, but that's not what i meant.

s i told in the first post, i have a value, e.g. 0x01D4629D

So why are you converting it to a float?
If it is meant to represent an integer, keep it as an integer type.
Converting to a floating point representation is utterly pointless, and explains why you're not seeing what you expect.

because 0x01D4629D is bigger than the limit of an integer... an integer can only hold 0xFFFF, while a double can hold 0xFFFFFFFF, that's why i thought i had to convert it to a double.

now if i use it as an integer, it only gives the last 2 bytes:

0x01D4629D returns 62 and 9D. And that's it. so no 01 and D4, which means it floods the value of an integer