Ваше предположение, что a - b
отрицательное, совершенно неверно.
Так как a
и b
имеют тип unsigned int
, все арифметические операции с этими двумя переменными выполняются в домене типа unsigned int
. То же самое относится и к смешанной арифметике «unsigned int
с int
». Такие операции реализуют арифметику по модулю, при этом модуль равен UINT_MAX + 1
.
Это означает, что выражение a - b
дает результат типа unsigned int
. Это большое положительное значение, равное UINT_MAX + 1 - 100
. На типичной платформе с 32-битной int
это 4294967296 - 100 = 4294967196
.
Выражение (a - b) * 2
также дает результат типа unsigned int
. Это также большое положительное значение (UINT_MAX + 1 - 100
умножается на 2
и берется по модулю UINT_MAX + 1
). На типичной платформе это 4294967096
.
Последнее значение слишком велико для типа int
. Это означает, что когда вы принудительно вставляете его в переменную result_i
, происходит переполнение целого числа со знаком. Результатом переполнения целого числа со знаком при назначении является определенная реализация. В вашем случае result_i
оказалось -200
. Это выглядит "правильным", но язык не гарантирует этого. (Хотя это может быть гарантировано вашей реализацией.)
Переменная result_u
получает правильный беззнаковый результат - положительное значение UINT_MAX + 1 - 100
. Но вы печатаете этот результат, используя спецификатор формата %d
в printf
вместо правильного %u
. Недопустимо печатать значения unsigned int
, которые не вписываются в диапазон int
, используя спецификатор %d
. По этой причине поведение вашего кода не определено. Значение -100
, которое вы видите в выводе, является просто проявлением этого неопределенного поведения. Этот вывод формально бессмысленен, хотя и кажется "правильным" на первый взгляд.
Наконец, переменная result_f
получает «правильный» результат выражения (a-b)*c
, вычисленный без переполнения, так как умножение выполняется в домене float
. То, что вы видите, это большое положительное значение, о котором я упоминал выше, умноженное на 2
. Однако он, вероятно, округляется до точности типа float
, которая определяется реализацией. Точное значение будет 4294967196 * 2 = 8589934392
.
Можно возразить, что последнее напечатанное вами значение — единственное, которое правильно отражает свойства беззнаковой арифметики, т. е. оно «естественным образом» получено из фактического результата a - b
.
person
AnT
schedule
09.07.2015