Я вычитаю числа без знака и сохраняю их в тип со знаком, и это просто работает. Я не до конца понимаю, почему это просто работает. Возьмите следующий пример:
#include <stdio.h>
int main(void)
{
uint32_t a = 1;
uint32_t b = 2;
int32_t c = a - b;
printf("%"PRId32"\n", c);
return 0;
}
Результат этого вычитания равен -1, и кажется, что это только -1, потому что мой компьютер является дополнением до двух. Я прав? Я смотрю на спецификацию C11.
Если мы выведем следующее утверждение:
int32_t c = a - b;
Начнем с того, что в соответствии с приоритетом оператора (как указано в аннотации 85 на стр. 76), вычитание:
a - b
C11 6.5.6 / 6:
Результатом бинарного оператора является отличие, полученное в результате вычитания второго операнда из первого.
Это -1 и поэтому не подходит. Преобразование! C11 6.3.1.3/2:
В противном случае, если новый тип не подписан, значение преобразуется путем многократного сложения или вычитания на единицу больше максимального значения, которое может быть представлено в новом типе, до значение находится в диапазоне нового типа.
Таким образом, фактическое значение a-b
равно 4294967295
. Далее, оператор присваивания: C11 6.5.16.1/2:
В простом присваивании (=) значение правого операнда преобразуется в тип выражения присваивания и заменяет сохраненное значение в объекте, обозначенном левым операндом.
Таким образом, значение без знака 4294967295
необходимо преобразовать в значение со знаком. Каковы правила? C11 6.3.1.3/3:
В противном случае новый тип подписывается и значение не может быть представлено в нем; либо результат определяется реализацией, либо генерируется определяемый реализацией сигнал.
Таким образом, это полностью определяется реализацией и, таким образом, заканчивается -1, поскольку такова моя реализация.
Это действительно так? Приведет ли код к другому значению, если я запусту его в системе с системой дополнения? Или я что-то пропускаю?