Выражение C отличается по-разному на двух разных компиляторах

У меня есть код, который работает по-разному между GCC и Atmel Studio:

uint32_t tc = 107900;
int8_t   m  = 59;

tc = tc - (m*1800);

В GCC результат в tc равен 1700, как и предполагалось.

С AtmelStudio результат в tc равен 132772, что неверно.

Проблема заключается в том, что термин m*1800 вычисляется с ограниченной точностью m с помощью AtmelStudio.

Мой вопрос в том, компилятор делает это правильно?

Спасибо.

Ответ 1

Оба делают это правильно. Выражение m * 1800 будет рассчитываться как тип int. Если int - 32 бита, то это будет 106200. Если int - 16 бит, что является вполне приемлемым способом реализации компилятора C, тогда он -24872.

Ответ 2

Кажется, что на AtmelStudio int - 16 бит, поэтому m*1800 переполняется, вызывая поведение undefined. В вашем случае поведение, предоставленное компилятором, вероятно, было уменьшением по модулю 65536 в диапазоне [-32768,32767], что дает -24872. Тогда tc - (m*1800) равно 132772.

Чтобы этого избежать, вам нужно указать либо m, либо 1800 на uint32_t или какой-либо другой тип (например, long), где результат не будет переполняться перед выполнением умножения.