Why do I need to cast the calculation...

unsigned long a = 250 * 96 * 64 * 2 / 512;  //= 4294967280 := wrong
unsigned long b = (unsigned long) 250 * 96 * 64 * 2 / 512; //=6000 := correct

Why do I need to cast ("(unsigned long)")?
I would expect the compiler to assume that every calculation after an "unsigned long a=" could lead to a value up to 2^32!

But it doesn't. It evaluates the expression (the RH side) treating each number as an int, and then assigns the result to wherever you want it. Promoting one of them to a long forces the calculation to be done using longs.

Consider this example:

  unsigned long a;
  byte b;
  float c;
  
  a = b = c = 250 * 96 * 64 * 2 / 512;

How should the numbers be treated? Float? Byte? Unsigned long? The answer is what I said, it evaluates the expression without seeing where the end result will go.

...thanks for the explanation, but for my taste the compiler should calculate with the needed resulution to get the (mathematically) right result and then assign from right to left:

  1. c = 6000
  2. b = (byte)c = 112
  3. a = b = 112

...but o.k., I take it as it is!

Try this:

  a = b = c = 250. * 96 * 64 * 2 / 512;
void setup ()
  {
  Serial.begin (115200);
  unsigned long a;
  byte b;
  float c;
  
  a = b = c = 250. * 96 * 64 * 2 / 512;
  
  Serial.println (a);
  }  // end of setup

void loop () { }

Output:

255

?

Joegi:
...thanks for the explanation, but for my taste the compiler should calculate with the needed resulution to get the (mathematically) right result and then assign from right to left:

  1. c = 6000
  2. b = (byte)c = 112
  3. a = b = 112

...but o.k., I take it as it is!

Some compiles do and others don't. This one dosn't. I once had the same piece of code give diffrent results because of this. One version was in a PC, the other was in an embedded system.