long from byte - one substracted?

Hi,

I’m getting crazy, just getting some bytes into an unsigned long;

simple code:

void setup() {
  Serial.begin(115200);
  byte test[] = { 0x0, 0x69, 0xA8, 0xC4 };
  unsigned long long1;
  long1 = (test[0] << 8) + test[1];
  Serial.print(long1,HEX); //gives 0x69, right
  long1 <<= 16;
  long1 += (test[2] << 8) + test[3];
  Serial.println();
  Serial.print(long1,HEX); //gives 0x68A8C4, wrong
}

void loop() {}

Getting 0x68A8C4 where it should read 0x69A8C4

I guess doing something fully wrong here, so whats the “right” way to put 4 bytes into a unsigned long :astonished: ?

TIA,

Michael

I guess doing something fully wrong here, so whats the "right" way to put 4 bytes into a unsigned long?

Bitwise-or.

Put a serial print in betweeen these

long1 <<= 16;
long1 += (test[2] << 8) + test[3];

see if the first shift is working.
may have to change that to
long1 = long1<<16;

I don’t see triple character operators on the reference page.

It's the long way home...

void setup() {
  Serial.begin(115200);
  byte test[] = { 0x0, 0x69, 0xA8, 0xC4 };
  unsigned long long1;
  longl = test[0];          // load
  longl = longl * 0x100;    // shift  
  longl = longl + test[1];  // load 
  longl = longl * 0x100;    // shift
  longl = longl + test[2];  // load
  longl = longl * 0x100;    // shift
  longl = longl + test[3];  // load
  Serial.print(long1,HEX);
}
long1 = (test[0] << 8) + test[1];

My guess is that test[1] is somehow being interpreted as -0x58 rather than as 0xA8.

Why such longwindednessocity?

void setup() {
  Serial.begin(115200);
  byte test[] = { 0x0, 0x69, 0xA8, 0xC4 };
  unsigned long long1 = (unsigned long)test[0] << 24 | (unsigned long)test[1] << 16 | (unsigned long)test[2] << 8 | (unsigned long)test[3];
  Serial.println(long1, HEX);
}

void loop()
{
}

Well, thanks ;)

Both variants, loading/shifting 1by1 (painfully long) and casting+shifting+or each single byte works. So far I thought when I shift 8 bits left and they fit into the register/variable, I always get 8 bits and not 8bit -1 on LSb :astonished: Now I'm just curious about the "why" and mainly how to avoid such a strange behavior in general. Casting every byte on every line before doing math with long? Are uint16 also prone to such weirdness when not explicit casted(?)

Michael

You need to type cast the byte values that you are attempting to left shift. Like this:

void setup() {
  Serial.begin(115200);
  byte test[] = { 0x0, 0x69, 0xA8, 0xC4 };
  unsigned long long1;
  long1 = ((unsigned int)test[0] << 8) + test[1];
  Serial.print(long1,HEX); //gives 0x69, right
  long1 <<= 16;
  long1 += ((unsigned int)test[2] << 8) + test[3];
  Serial.println();
  Serial.print(long1,HEX); //gives 0x68A8C4, wrong
}

void loop() {}

Adding works, but bitwise OR is better(more clear) as somebody else already said.

Love a little code golf. This problem can be worked without any arithmetic using a C union to allow two views of the same static memory:

union {
	long thelong;
	byte thebytes[4];
} u;

void setup() {
	Serial.begin(57600);
}

void loop() {
	u.thebytes[3] = 0x00;
	u.thebytes[2] = 0x69;
	u.thebytes[1] = 0xa8;
	u.thebytes[0] = 0xc4;
	Serial.print(u.thelong, HEX);
	delay(10000);
}

Prints 69A8C4

-br

The problem lies here:

  long1 += (test[2] << 8) + test[3];

The right hand side is an integer whose hex value is 0xA8C4 but as a signed 16-bit integer it is -22332. Because it is being added to the long integer, it is first sign extended to make it 0xFFFFA8C4. Adding that to 0x00690000 gives 0x0068A8C4.

Pete

majenko: Why such longwindednessocity?

I do it that way, basically, but not so chunky as that. I thought I would stay with the OP's paradigm.

afremont: Adding works, but bitwise OR is better(more clear) as somebody else already said.

A shift left is multiplying said number by 2^n (where n is the number of bits to go left).

That and seeing the solution didn't involve using the slider bar. :)