10

I have code that is running differently between GCC and Atmel Studio:

uint32_t tc = 107900;
int8_t   m  = 59;

tc = tc - (m*1800);

On GCC, the result in tc is 1700, as intended.

With AtmelStudio, the result in tc is 132772, which is not correct.

The problem seems to be that the m*1800 term is being computed with the limited precision of m with AtmelStudio.

My question is, which compiler is doing it correctly?

Thank you.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
NXT
  • 1,855
  • 2
  • 18
  • 36
  • 4
    I would imagine that casting `m` to `uint32_t` in the expression (i.e. `tc = tc - ((uint32_t)m * 1800)`) would produce the desired results, but I'm not sure that it's required by the C language specs. – Jonathon Reinhart Apr 16 '14 at 02:27
  • 1
    ... or use `(m*1800L)` since the arithmetic product of 59*1800 does not fit in the _minimum_ C specified `int` range of -32767 to +32767 but does fit in the _minimum_ C specified `long` range. – chux - Reinstate Monica Apr 16 '14 at 02:51
  • Obviously this compiler uses 16 bit integers by default. Expected behaviour. – david.pfx Apr 19 '14 at 06:09

2 Answers2

10

It seems that on AtmelStudio, int is 16-bit, so m*1800 overflows, invoking undefined behavior. In your case, the behavior the compiler gave was probably reduction modulo 65536 into the range [-32768,32767], yielding -24872. Then tc - (m*1800) is 132772.

To avoid this you need to cast either m or 1800 to uint32_t or some other type (e.g. long) where the result won't overflow before doing the multiplication.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
6

Both are doing it correctly. The expression m * 1800 will be calculated as type int. If int is 32 bits, then it will be 106200. If int is 16 bits, which is a perfectly acceptable way to implement a C compiler, then it's -24872.

Lee Daniel Crocker
  • 12,927
  • 3
  • 29
  • 55