HEX and BIn conversion for unsigned long data type wrong (Closed)

For some project I'd like to store boolean parameters into eeprom.
However, I ran into a problem when I got returned a different number than I put in.
After some testing it seems that some conversions are calculated wrong.
In those cases the 1st bit of the second most significant byte is set to 0.
It gets even worse if a variable is used for the most to least significant bytes.
Am I doing something wrong? It ain't a bug?
I can't find anything where this is mentioned.
Nobody would probably use these kind of notations (it's for testing now), but it should work shouldn't it?

// When composing a long data type, in certain cases the 1st bit of the 2nd most significant byte (byte 2) is set to 0
// Using a variable for the multiplier even sets all bits of bytes 2 and 3 to 1.

unsigned long calculatedvalue=(B11111111 * 16777216) + (B11111111 * 65536) + (B11111111 * 256) + (B11111111); //Binairy conversion: bit 1 of byte 2 is wrong
//unsigned long calculatedvalue=(0xFF * 16777216) + (0xFF * 65536) + (0xFF * 256) + (0xFF);                     //Hex conversion: bit 1 of byte 2 is wrong
//unsigned long calculatedvalue=(0xFF * 16777216) + (0xFFFFFF);                                                 //Hex conversion: correct.
//unsigned long calculatedvalue=(0xFF * 16777216) + (0xFF * 65536) + (0xFFFF);                                  //Hex conversion: correct.
//unsigned long calculatedvalue=(0xFFFF * 65536) + (0xFF * 256) + (0xFF);                                       //Hex conversion: bit 1 of byte 2 is wrong
//unsigned long calculatedvalue=(0xFFFF * 65536) + (0xFFFF);                                                    //Hex conversion: correct.
//unsigned long calculatedvalue=0xFFFFFFFF;                                                                     //Hex conversion: correct.
//unsigned long calculatedvalue=(255 * 16777216) + (255 * 65536) + (255 * 256) + (255);                         //Decimal: bit 1 of byte 2 is wrong
//unsigned long calculatedvalue=(255 * 16777216) + (16777215);                                                  //Decimal: correct.
//unsigned long calculatedvalue=(255 * 16777216) + (255 * 65536) + (65535);                                     //Decimal: correct.
//unsigned long calculatedvalue=(65535 * 65536) + (255 * 256) + (255);                                          //Decimal: bit 1 of byte 2 is wrong
//unsigned long calculatedvalue=(65535 * 65536) + (65535);                                                      //Decimal: correct.
//unsigned long calculatedvalue=4278190080 + 16711680 + 65280 + 255;                                            //Decimal: correct.
unsigned long expectedValue=4294967295;

// Testing with multiplier via variable.
// Now bytes 2 and 3 are converted to all ones.
// It doesn't matter if the value of the multiplier is in Hex of decimal notation.
int multiplierB0=0x1;       //Multiplier least significant byte
int multiplierB1=0x100;     //Multiplier 2nd least significant byte
int multiplierB2=0x10000;   //Multiplier 2nd most significant byte
int multiplierB3=0x1000000; //Multiplier most significant byte
//unsigned long calculatedvalue=(B10001111 * multiplierB3) + (B10000111 * multiplierB2) + (B10000011 * multiplierB1) + (B10000001);
//unsigned long expectedValue=2407957377;

void setup() {

  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  Serial.println("Binairy:\t\tMost to least significant byte -->");
  Serial.println("\t\t\t3       2       1       0");
  Serial.println("\t\t\t76543210765432107654321076543210");
  Serial.print("Expected value :\t");
  Serial.println(expectedValue, BIN);
  Serial.print("Calculated value :\t");
  Serial.println(calculatedvalue, BIN);
  Serial.println("");
  Serial.println("Hexidecimal:\t\t3 2 1 0");
  Serial.print("Expected value :\t");
  Serial.println(expectedValue, HEX);
  Serial.print("Calculated value :\t");
  Serial.println(calculatedvalue, HEX);

}

void loop() {

}

Am I doing something wrong? It ain't a bug?

Yes you are doing something wrong and it is a bug in your code!

Mark

Where is the error?

int multiplierB2=0x10000;   //Multiplier 2nd most significant byte
int multiplierB3=0x1000000; //Multiplier most significant byte

Will those values actually fit in an int?

Switch on the warnings and let the compiler answer your question.

Somewhere\Badhexbin\Badhexbin.ino:6:44: warning: integer overflow in expression [-Woverflow]

 unsigned long calculatedvalue = (B11111111 * 16777216) + (B11111111 * 65536) + (B11111111 * 256) + (B11111111); //Binairy conversion: bit 1 of byte 2 is wrong

                                            ^

Somewhere\Badhexbin\Badhexbin.ino:6:91: warning: integer overflow in expression [-Woverflow]

 unsigned long calculatedvalue = (B11111111 * 16777216) + (B11111111 * 65536) + (B11111111 * 256) + (B11111111); //Binairy conversion: bit 1 of byte 2 is wrong

                                                                                           ^
Somewhere\Badhexbin\Badhexbin.ino:26:20: warning: overflow in implicit constant conversion [-Woverflow]

 int multiplierB2 = 0x10000; //Multiplier 2nd most significant byte

                    ^

Somewhere\Badhexbin\Badhexbin.ino:27:20: warning: overflow in implicit constant conversion [-Woverflow]

 int multiplierB3 = 0x1000000; //Multiplier most significant byte

                    ^

If you want to store bools in EEPROM why don't you just do that?

Or do you want to pack 8 bools into a single byte? If so do simple bitwise operators or use bitWrite() and bitRead().

PaulS:

int multiplierB2=0x10000;   //Multiplier 2nd most significant byte

int multiplierB3=0x1000000; //Multiplier most significant byte



Will those values actually fit in an int?

PaulS:

int multiplierB2=0x10000;   //Multiplier 2nd most significant byte

int multiplierB3=0x1000000; //Multiplier most significant byte



Will those values actually fit in an int?

Right! Of course! Thanks!

Whandall:
Switch on the warnings and let the compiler answer your questions.

I'll do. Didn't know that option.
Thanks a lot for helping this newbie.

I think having warnings disabled as a default is a bad decision of the arduino team.

septillion:
If you want to store bools in EEPROM why don't you just do that?

Or do you want to pack 8 bools into a single byte? If so do simple bitwise operators or use bitWrite() and bitRead().

8, 16, 32... don't know yet.
Was just playing around.
16 went ok, but 32 turned out a bit more difficult.
I did find bitshifting and bitWrite etc. Thanks
I may end up using that.

32 bit should have worked fine. Its 64 bits where bitRead()/bitWrite() don't work. Post your 32 bit code.

PaulRB:
32 bit should have worked fine. Its 64 bits where bitRead()/bitWrite() don't work. Post your 32 bit code.

The execution of the following codes does not support your opinion?

void setup() 
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);  //L is OFF
  uint64_t x = 0x8234567812345678;//1000 0010 0011 0100 0101 0110 0111 1000, ..., 1000.
  bool n = bitRead(x,63);
  Serial.print(n, BIN); //shows 1
  bitWrite(PORTB, 5, bitRead(x, 63)); //L is ON
}

void loop() 
{

}

bitRead() works with 64-bit values, but bitSet(), bitClear() and bitWrite() are limited to 32 bits because of that 1UL in the macros:

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))

oqibidipo:
bitRead() works with 64-bit values, but bitSet(), bitClear() and bitWrite() are limited to 32 bits because of that 1UL in the macros:

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)

#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))

Thanks with for the valuable information.

ffokke:
8, 16, 32... don't know yet.
Was just playing around.

My point was, each EEPROM address can only hold a single byte aka 8-bit. Yeas, with .put() you can place a 16 or 32-bit value in EEPROM but it's then split into 2/4 bytes again. Aka, going beyond 8-bits is a bit pointless. Otherwise you do stuff to pack it and the first thing .put() does is splitting it again.