Преобразование происходит . Проблема в том, что выражение anUInt << 2
представляет собой unsigned int
, поскольку anUInt
представляет собой unsigned int
.
Преобразование anUInt
в long long
(на самом деле это преобразование в данном конкретном случае) является правильным решением.
Ни (type)var << 1
, ни ((type)var) << 1
не являются более корректными или переносимыми, поскольку приоритет оператора строго определен Стандартом. Тем не менее, последний, вероятно, лучше , потому что его легче понять людям, которые небрежно смотрят на код. Другие могут не согласиться с этим утверждением.
EDIT:
Обратите внимание, что в вашем первом примере:
unsigned char anUChar = 0xc0;
int anInt = anUChar << 2;
... результат выражения anUChar << 2
- это не unsigned char
, как вы могли бы ожидать, а int
из-за интегрального продвижения.
Операнды operator<<
являются целочисленными или перечислимыми (см. Стандарт 5.8 / 1). Когда вызывается бинарный оператор, который ожидает операнды арифметического или перечислимого типа, компилятор пытается преобразовать оба операнда в один и тот же тип, чтобы выражение могло привести к общему типу. В этом случае интегральное продвижение выполняется для обоих операндов (5/9). Когда unsigned char
принимает участие в интегральном повышении, оно будет преобразовано в int
, если ваша платформа может вместить все возможные значения unsigned char
в int
, в противном случае оно будет преобразовано в unsigned int
(4.5 /1).