Pages: [1]   Go Down
Author Topic: Where to report compiler bug?  (Read 858 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Edison Member
*
Karma: 49
Posts: 1676
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I ran into a problem with the way that the compiler handles multiplication of integers.
This code:
Code:
void setup(void)
{
  int x,y,z;
 
  Serial.begin(115200);
 
  x = 1024;
  y = 1024;
  z = (x*y)>>14;
  // This prints zero - should be 64
  Serial.println(z);
  z = ((long)x*y)>>14;
  // This prints 64
  Serial.println(z);
while(1); 
}

void loop(void){}
prints:
Quote
0
64

The first print should also be 64 - not zero. (x*y) multiplies 16-bit ints together which produces a long result. C retains this for as long as it can so that the shift operator >>14 will shift the long integer down 14 bits to give a result of 64 but the compiler is apparently converting the intermediate result to a 16-bit int before it should and ths results in zero. The second multiplication "((long)x*y)" explicitly forces the multiply be done as a long and produces the correct result.

The equivalent version of this sketch when compiled using either MSVC or the Cygwin GCC compiler prints 64 for both multiplications as they should.

If you change the sketch to its equivalent form using char instead of int, it gets it right. i.e. this:
Code:
void setup(void)
{
  char x,y,z;
 
  Serial.begin(115200);
 
  x = 64;
  y = 64;
  z = (x*y)>>10;
  // This prints 4
  Serial.println((int)z);
  z = ((int)x*y)>>10;
  // This prints 4
  Serial.println((int)z);
while(1); 
}

prints:
Quote
4
4
The first multiplication involves two 8-bit signed integers and the result is a 16-bit signed integer which is then shifted down before being assigned to an 8-bit integer.

Where do I report this problem?

Pete
Logged

Austin, TX
Offline Offline
God Member
*****
Karma: 12
Posts: 524
carpe diem
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

See here for the integer conversion rules:

https://www.securecoding.cert.org/confluence/display/seccode/INT02-C.+Understand+integer+conversion+rules

In your first example, since all the variables are integers, no conversion will take place.

In the second example, since the variable are smaller than int, they will be promoted to int before the operation is performed.

The reason it appears to work in MSVC is that they use 4 byte integers.
Logged

Offline Offline
Edison Member
*
Karma: 49
Posts: 1676
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh rats.

Thanks very much :-)

Pete
Logged

Pages: [1]   Go Up
Jump to: