Serial monitor only printing last half of long after being deconstructed

hi there

i have been struggling to get my head round deconstructing and reconstructing a long data type into bytes and back again. I posted on the arduino stack exchange and received lots of helpful answers with example code which have helped greatly with my understanding. However, not enough to spot the issue below.

My Stack Exchange Forum Post

As stated, this code was written by someone else (oh.dae.su), the only issue is that it will print the following to the serial monitor;

Original:
12345678
Individual bytes:
78
56
34
12
Reconstructed:
5678

As can be seen, it only prints the last half of the reconstructed answer. The author of this code has tested it on his nodemcu and gets the right answer. So what am i missing that means i get a different answer? I have placed his code first, and then mine. I have added the following lines;

void setup(){
Serial.begin(9600);
}
void loop() {
  long a=0x12345678, c=0;
  byte b[4];
  Serial.println("Original:");
  Serial.println(a,HEX);
  delay(1000);
  Serial.println("Individual bytes:");
  for (int i=0; i<4; i++)
  {
    b[i]=((a>>(i*8)) & 0xff); //extract the right-most byte of the shifted variable
    Serial.println(b[i],HEX);
    delay(1000);
  }

  for (int i=0; i<4; i++)
  {
    c+=b[i]<<(i*8);
  }
  Serial.println("Reconstructed:");
  Serial.println(c,HEX);
  delay(1000);
}
void setup(){
Serial.begin(9600);
}
void loop() {
  long a=0x12345678, c=0;
  byte b[4];
  Serial.println("Original:");
  Serial.println(a,HEX);
  delay(1000);
  Serial.println("Individual bytes:");
  for (int i=0; i<4; i++)
  {
    b[i]=((a>>(i*8)) & 0xff); //extract the right-most byte of the shifted variable
    Serial.println(b[i],HEX);
    delay(1000);
  }

  for (int i=0; i<4; i++)
  {
    c+=b[i]<<(i*8);
  }
  Serial.println("Reconstructed:");
  Serial.println(c,HEX);
  delay(1000);
}

Any help would be greatly appreciated. Many Thanks, Ross

Cast your bytes to unsigned long before left shift.

that sorted it. I changed the following section from;

  for (int i=0; i<4; i++)
  {
    c+=b[i]<<(i*8);
  }

to

  for (int i=0; i<4; i++)
  {
    c+= ((uint32_t) b[i]) <<(i*8);
  }

Two questions. First, does it need to be cast to an unsigned long to stop it shifting the data into the “bit-bucket”? and secondly, is there a more efficient way to cast a variable than this as it would be performing the same operation 4 times in the loop? i tried casting above the loop but it didn’t work?

Thankyou for your help.

It needs to be cast because arithmetic on the RHS of the = defaults to "int" arithmetic, which on eight bit AVRs is signed sixteen bit.

Ross46:
is there a more efficient way to cast a variable than this as it would be performing the same operation 4 times in the loop? i tried casting above the loop but it didn’t work?

Yes but at the expense of memoryunsigned long b[4];
and i think also like this

  for (int i=3; i>-1; i--)
  {
     c=c<<8;   //or like this c<<=8; i saw something done in that manner recently..
     c+=b[i];
  }

i hope this was the final edit (sorry…)