Почему C ++ печатает беззнаковое значение char как отрицательное?

Я пытаюсь понять правила неявного преобразования в C ++, и я понял, что когда есть одна операция между двумя основными типами, «нижний тип» переводится в «более высокий тип», поэтому, скажем, для:

int a = 5;
float b = 0.5;

std::cout << a + b << "\n";

должен напечатать 5.5, потому что ‘a’ повышен до типа с плавающей точкой. Я также понял, что неподписанные типы являются «более высокими типами», чем подписанные части счетчика, поэтому:

int c = 5;
unsigned int d = 10;

std::cout << c - d << "\n";

печатает 4294967291, потому что ‘c’ переводится в unsigned int, и так как типы unsigned оборачиваются, когда меньше нуля, мы получаем это большое число.

Однако в следующем случае я не понимаю, почему я получаю -105 вместо положительного числа.

#include <iostream>

int main(void) {
unsigned char a = 150;
std::cout << static_cast<int>(a - static_cast<unsigned char>(255)) << "\n";
return 0;
}

Я думаю, что этот код:

a - static_cast<unsigned char>(255)

должно приводить к положительному числу, чтобы окончательное приведение (к int) не влияло на конечный результат, верно?

3

Решение

Цитировать из C++14Глава § 5.7

Аддитивные операторы + а также - группа слева направо. Обычные арифметические преобразования выполняются для
операнды арифметического или перечислимого типа.

и для обычные арифметические преобразования, (специально для этого случая)

….

  • В противном случае интегральные преобразования (4.5) должны выполняться для обоих операндов.

и, наконец, для интегральные акции, глава § 4.5

Значение типа integer, отличного от bool, char16_t, char32_t, или же wchar_t чье целочисленное преобразование
rank (4.13) меньше ранга int, который можно преобразовать в тип prvalue int если int может представлять все
значения типа источника; в противном случае исходное значение может быть преобразовано в значение типа unsigned
int.

Следовательно unsigned char операнды повышены до int а затем, результат рассчитывается.

2

Другие решения

Вы пропускаете (неявное) преобразование из unsigned char в int что происходит, чтобы выполнить - (вычесть) операцию. Это целочисленное продвижение происходит каждый раз, когда вы пытаетесь применить любую целочисленную операцию к значению некоторого целочисленного типа, меньшего, чем int,

4

Здесь есть ответы, показывающие, что происходит. Я не буду повторяться Я собираюсь дать вам простой инструмент, чтобы помочь вам.

Вот трюк, который вы можете сделать, чтобы быстро найти тип выражения:

template <class> struct Name; // purposely no definition given

Name<decltype(your_expression)> n;

Это сгенерирует ошибку компилятора для неопределенного шаблона «Имя», но на самом деле нас интересует тип аргумента шаблона, который появится в сообщении об ошибке.

Например. если вы хотите увидеть, какой тип вы получаете, когда вы делаете арифметику между двумя unsigned char:

#include <utility>
template <class> struct Name;

auto test()
{
Name<decltype(std::declval<unsigned char>() - std::declval<unsigned char>())> n;

// or
unsigned char a{};
Name<decltype(a - a)> n2;
}

получу тебя

error: implicit instantiation of undefined template 'Name<int>'

который покажет вам, что тип выражения int

Конечно, это не скажет вам, какие правила применяются, но это быстрая отправная точка, чтобы увидеть тип выражения или проверить ваше предположение о типе выражения.

2
По вопросам рекламы [email protected]