Why does an unsigned long constant declaration give the wrong value?

For my timer application I tried to define a constant for 15 minutes in milliseconds as follows:

const unsigned long Alarm = 1000 * 60 * 15 ;

However the alarm didn't sound after 15 minutes. Eventually I tracked down the problem by inserting Serial.println(Alarm); which printed 4294949792 rather than the expected 900000. Changing the const declaration as follows fixed the problem:

const unsigned long Alarm = 900000 ;

What's going on here?

The compiler is doing int math. put "ul" after all your constants: 1000ul60ul15ul

Or just do this: const unsigned long Alarm = 900000;

What KeithRB wrote is true and safe, but I would have written:

The compiler is doing int math. put "ul" after your first constant: 1000UL6015

Two things to notice:

  1. With UL after the first constant, all the rest of the math should be performed as unsigned long.

  2. UL stands out more than ul, and avoids confusing the lower case ell with the digit one.

Thanks for the answers.

Why doesn't the compiler know to use unsigned longs after a const unsigned long declaration?

Why doesn't the compiler at least give a warning?

Why doesn't the compiler at least give a warning?

Warnings are suppressed in the Arduino environment.

Why doesn't the compiler know to use unsigned longs after a const unsigned long declaration?

Because that is not what you might always want to do. As soon as you make the compiler second guess what you meant to do rather than what you said you wanted to do it becomes an impossible language to work with. No language does that, that is what wives are for.

Wives are there to second-guess you, or there to be impossible to work with?

The "unsigned long" on the left hand side of the equal sign only affects the definition of the variable, and the way that the final result is placed into that variable. Until the calculation of the right hand side is complete, the "unsigned long" on the left hand side is ignored. That's just the way that it is defined in C and C++.

(Because of things like pointers and ++ and --, I think that the technical definition is probably more complicated than what I have stated, but for practical cases like this one the simple definition is fine.)

Thank you - that's helpful.

This very problem caught me recently.

Now that I've gone back and read my K&R C book, I can't say the Arduino compiler is doing anything wrong. It's not particularly helpful, but not wrong.

I tried one other C compiler though (On MacOS 10.11.2), and it doesn't have this problem. It produces the unsigned long result you expect.

So maybe this should be a request for enhancement somewhere. I've got no idea where.

The Arduino compiler is like every other thing that's computer related, by the the time its perfect and bug free its obsolete.

Had this problem also but did "solve" it with the "900000" version. Good to know what the reason was now! With the multiplication codes is much better readable! Thanks for this question and for the answers of cause!