Существует набор преобразований, называемых обычными арифметическими преобразованиями , которые используются до оценки большинства арифметических операторов.
В принципе, вы можете рассмотреть несколько правил арифметики для целых чисел:
Во-первых, целочисленная арифметика никогда не выполняется с операндами, меньшими int
, поэтому в случае short * signed char
оба операнда short
и signed char
переводятся в int
, два значения int
умножаются, а затем получается int
.
Во-вторых, если один или оба типа «больше» int
, компилятор выбирает тип, который по крайней мере «такой же большой», как тип наибольшего операнда. Итак, если у вас есть long * int
, int
повышается до long
, а в результате получается long
.
В-третьих, если любой из операндов равен unsigned
, то результат не подписывается. Таким образом, если у вас есть long * unsigned int
, long
и unsigned int
оба повышаются до unsigned long
, и в результате получается unsigned long
.
Если любой из операндов имеет тип с плавающей точкой, то выполняется арифметика с плавающей точкой: float
, double
или long double
(который зависит от типов операндов; полная таблица используется для определения Тип результата можно найти на странице, на которой есть ссылка в начале этого ответа).
Обратите внимание, что тип результата не зависит от значений операндов . Тип должен быть выбран компилятором во время компиляции, прежде чем значения станут известны.
Если результат s * i * i
выходит за пределы диапазона типа результата (int
, в вашем сценарии), то вам не повезло: ваша программа не может принять решение во время выполнения: «О, я должен переключиться на использование long
! " потому что тип результата должен был быть выбран во время компиляции.