Я не уверен, когда мне нужно беспокоиться о переполнении при использовании неподписанных символов. Этот случай ясен:
uint8_t a = 3;
uint8_t b = 6;
uint8_t c = a - b; // c is 253
Однако что здесь происходит:
float d = a - b; // d is -3
Являются ли оба a и преобразованы в float перед выполнением вычитания?
Или также в этом случае:
float e = (a - b) + (a - c);
Все три переменные преобразованы в число с плавающей точкой?
Возможны ли случаи переполнения, даже если назначаемая переменная является плавающей точкой? Правила одинаковы, если е это float, или int, или что-нибудь еще?
Кроме того, что происходит в таком случае:
int a = std::abs(a - b);
Ваш случай не является результатом преобразования char-to-float, но обусловлен целочисленными правилами продвижения.
Cppreference утверждает следующее (выделение мое):
Значения малых целочисленных типов (таких как char) могут быть преобразованы в значения больших целых типов (таких как int). Особенно, арифметические операторы не принимают типы, меньшие чем int, в качестве аргументов, и интегральные продвижения автоматически применяются после преобразования lvalue в rvalue, если это применимо. Это преобразование всегда сохраняет значение.
А также:
unsigned char или unsigned short могут быть преобразованы в int, если они могут содержать весь диапазон значений, и unsigned int в противном случае.
Так что в вашем случае -
Оператор преобразует значения в целые числа, которые затем конвертируются в числа с плавающей точкой. Только назначение c
преобразует обратно в uint8_t
(который переполняет).
То же самое относится к std::abs
пример: значения преобразуются перед вычитанием, а результат передается в функции.
Для получения дополнительной информации о подписанных / неподписанных продвижениях по арифметическим операциям, смотрите, например, этот ответ: https://stackoverflow.com/a/6770275/3198247