Concatenation of operations yields wrong result

Hi. Weird issue here:

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

long i;
byte command=80;

void loop(){
  i=((int)command)*1000;
  Serial.println(i);
  delay(100);
}

For whatever reason this outputs 14464

However if i split the operation into:

  i=((int)command);
  i*=1000;

I get 80000 as expected.

Ideas?

Tks

  i=((int)command)*1000;

The right side of this expression evaluates to an int, which overflows.

The range for an int is +32k to -32k-1. You rolled over.

Look at ints in the reference section of this site.

Mark

Mishap then.
Tks

Try this:

  i=command*1000L;

The L suffix causes the literal 1000 to be evaluated as a long, which, if I understand type promotion correctly, should then promote the command to a long as well, avoiding rollover. You can, if desired, also use the suffix UL to force a literal to an unsigned long.

i is still and int so no L and UL wont help.

Mark

holmes4:
i is still and int so no L and UL wont help.

What am I missing? Looks like i is a long to me:

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

long i;
byte command=80;

void loop(){
  i=((int)command)*1000;
  Serial.println(i);
  delay(100);
}

i is still and int so no L and UL wont help.

Yes, it will. i will be promoted to a long, since the remaining operands are long, and long operations will be performed, with long results.

Without the L suffix on the constant, the operands are all ints, so int operations are performed, with int results.

@PaulS

Yes but the you assign the result to i which is a 16 bit signed int so you still get 14646(or so). i needs to be long. Try running the program (after some sleep).

Mark

Yes but the you assign the result to i which is a 16 bit signed int so you still get 14646(or so).

The post title says "Concatenation of operations yields wrong results". It mentions nothing about assigning a value to a variable.

Adding the L to the constant (and removing the useless cast) WILL result in the correct result. That the now correct result is assigned to a variable of the wrong size/type is a separate problem.

But, yeah, I did miss the point you were trying to make, I guess.

Yes but the you assign the result to i which is a 16 bit signed int

I'm still struggling with your point, holmes4.

long i;

Signed, yes, but not 16 bit.

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

long i;
byte command=80;

void loop(){
  i=((int)command)*1000;
  Serial.println(i);
  delay(100);
}

((int)command)*1000;
this is 2 ints and the result is computed as an int > 65535 so it overflows

i=
this is where the overflowed int gets promoted to 32 bit and assigned to long i.

But i is not long and you can't promote the LHS of the assignment in that way. The = trunicates the value from the RHS to fit in the 16 bit int of the LHS.

Try running the program I DID!.

Mark

But i is not long

What does Serial.println (sizeof (i)); print?

here, I'll make it easier. here's the code from the original post up there ^^^, with one line added

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

long i;
byte command=80;

void loop(){
  i=((int)command)*1000;
  Serial.println(i);
  Serial.println(sizeof (i));
  delay(100);
}

Nothing up my sleeve, honest.

I think i'll get my eyes tested I could sware thr i was an int not a long. :~

Mark

holmes4:
But i is not long and you can't promote the LHS of the assignment in that way. The = trunicates the value from the RHS to fit in the 16 bit int of the LHS.

Try running the program I DID!.

Mark

Read the code. That's why I bothered to quote it. It says

long i;

The int is in

i=((int)command)*1000;

Everything on the RHS is type int. The LHS is declared long.

Do you have some form of dyslexia? If not then slow down, code is not jokes from reader's digest.

I think i'll get my eyes tested I could sware thr i was an int not a long.

I wonder if that would help your spelling? :slight_smile: