6

Executing the following code always gives -511 as a result, I performed many tests, and it seems that results are correct from 0 * 0 to 181 * 181, beyond that, results are abnormal, I tried many types for the z variable (int, long, float) without success, any idea? I'm using the Arduino Uno.

long z = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
 z = 255 * 255;
 Serial.println(z);
 delay(200);
} 
Michel Keijzers
13k7 gold badges41 silver badges58 bronze badges
asked Feb 5, 2019 at 9:36
5
  • 2
    Hint: Try "z = 255 * 255L;" or "z = 255 * (long) 255;" Commented Feb 5, 2019 at 10:25
  • I did. @MikaelPatel I worked indeed, could you explain the reason behind this, and is there similar cases for other types? Commented Feb 5, 2019 at 10:32
  • 4
    This "bug" is as old as programming. When you write "255" compiler creates an "integer constant" with value of 255. When you multiply 255 by 255 you multiply two "integer constants" and by convention result of such multiplication is an "integer". Then you implicitly cast it to long when doing assignment. When you multiply "255" by "255L" you actually multiply "integer constant" by "long constant" and result of such multiplication is "long". You will see similar issue when you write float z = 1 / 5 result will be 0 because integer division results with integer that is later casted to float. Commented Feb 5, 2019 at 10:54
  • 3
    Ref: gcc.gnu.org/wiki/avr-gcc is all the information you need for the AVR GCC compiler. It all has to do with 1) number range of "int" for a given target, and 2) compiler evaluation of constant expressions. Commented Feb 5, 2019 at 11:03
  • @MikaelPatel You should answer the questions instead of writing snippets of them in the comment section. Commented Feb 5, 2019 at 12:57

2 Answers 2

12

No, this is not a bug. You are using a compile time constant expression which is signed int unless told otherwise. Therefore you can only represent numbers between -32768 and 32767. Your computation of 255 * 255 = 65025 exceeds the range. Thus you see an overflow. In the C/C++ standard the overflow of signed types is actually undefined behavior. That means that the compiler is allowed to do anything from showing the correct answer to halt and catch fire. Only unsigned types with a known size like uint16_t have a well-defined overflow behaviour. You should promote your right hand side computation to unsigned type like this:

z = 255U * 255U;

This way you tell the compiler your intention and don't land in "Undefined-Behaviour-Land".

linhartr22
6065 silver badges10 bronze badges
answered Feb 5, 2019 at 9:51
2
  • @Juraj Right, I thought it was signed 16 bit just as int. But the latter is still true. Compile time constants are signed int, which is 16 bit. So the right side of the assignement is the problem. Commented Feb 5, 2019 at 10:39
  • wrap around doesn't sound right - but I know what you're saying Commented Feb 5, 2019 at 11:37
0

Assuming long is 4 bytes, it should work.

However, if somehow a long type is only 2 bytes, or (more likely) you used another type or there is some wrong define/typedef, and it is a signed long (default if you do not used the unsigned keyword), the value range is -32,768 to 32,767 and 255 * 255 = 65,025 which is out of range.

So you can first try to use unsigned long.

Juraj
18.3k4 gold badges31 silver badges49 bronze badges
answered Feb 5, 2019 at 9:51
6
  • long is -2,147,483,648 to 2,147,483,647 Commented Feb 5, 2019 at 10:30
  • With unsigned long the result becomes :4294966785. Commented Feb 5, 2019 at 10:40
  • Kwasmich's answer is correct Commented Feb 5, 2019 at 10:44
  • @Juraj - one short there :p Commented Feb 5, 2019 at 11:36
  • 2
    it is not. Kwasmich explains Commented Feb 5, 2019 at 13:42

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.