Результат побитового оператора в С++

Тестирование нескольких компиляторов (Comeau, g++) подтверждает, что результатом побитового оператора некоторого "целочисленного типа" является int:

void foo( unsigned char );
void foo( unsigned short );

unsigned char a, b;

foo (a | b);

Я бы ожидал, что тип "a | b" будет unsigned char, так как оба операнда без знака char, но компиляторы говорят, что результатом является int, а вызов foo() является неоднозначным. Почему язык разработан так, что результатом является int или эта реализация зависит?

Спасибо,

Ответ 1

Это стандартное поведение на С++ (ISO/IEC 14882):

5.13/1 Побитовое включение оператора OR

Обычные арифметические преобразования выполнено; результатом является поразрядное включительно ИЛИ из его операндов. Оператор применим только к интегралу или перечисляющие операнды.

5/9 Обычные арифметические преобразования

Многие бинарные операторы, которые ожидают операнды арифметики или перечисления тип вызывает конверсии и доходность аналогичным образом. Цель должен дать общий тип, который также тип результата. Эта шаблон называется обычной арифметикой конверсий, которые определяются как следующим образом:

  • Если любой из операндов имеет тип long double, другой должен быть преобразован в long double.
  • В противном случае, если любой операнд double, другой должен быть преобразован в double.
  • В противном случае, если любой операнд float, другой должен быть преобразован в float.
  • В противном случае интегральные акции должны выполняться в обоих операндах.
  • ...

4.5/1 Интегральные акции

Значение типа char, signed char, unsigned char, short int или unsigned short int могут быть преобразованы в rvalue типа int, если int может представляют все значения источника тип; в противном случае значение r источника может быть преобразуется в значение r типа unsigned int.

Я думаю, что это связано с int якобы "естественным" размером для среды исполнения, чтобы обеспечить эффективную арифметику (см. ответ Чарльза Бейли).

Ответ 2

Я бы ожидал, что тип "a | b" будет unsigned char, так как оба операнда без знака char,

Мое чтение некоторых начинающих книг C в прошлом оставило впечатление, что побитовые операторы остались на языке только для целей системного программирования и, как правило, следует избегать.

Операторы выполняются самим процессором. CPU использует для регистров операндов (которые, безусловно, больше, чем char), и, таким образом, компилятор не может знать, сколько бит регистра будет зависеть от операции. Чтобы не потерять полный результат операции, компилятор подгоняет результат к правильной работе. AFAICT.

Почему язык разработан так, что результатом является int или эта реализация зависит?

Представление данных на уровне бит на самом деле определяется реализацией. Это может быть причиной того, что, по-видимому, бит-мульные операции также определяются при реализации.

Хотя C99 определяет в 6.2.6.2 Integer types, как они должны появляться и вести себя (и позже, как побитовые операции должны работать), конкретная глава дает большую свободу для реализации.

Ответ 3

Кажется, это то же самое, что и в Java:

Короткие и char (и другие целые числа, меньшие, чем int), являются более слабыми типами, чем int. Поэтому каждая операция над этими более слабыми типами автоматически распаковывается в int.

Если вы действительно хотите получить короткий текст, вам придется его выводить.

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

Ответ 4

Не short не совпадает с short int? таким же образом, что long является синонимом int. например. a short является int, занимающим меньше памяти, а затем стандартным int?

Ответ 5

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

Если язык был определен без цельной рекламы, многие многошаговые вычисления, которые в противном случае могли бы быть естественным образом отображены непосредственно в машинные инструкции, возможно, должны быть перемежены с помощью операций маскирования, выполняемых на промежуточных элементах, чтобы генерировать "правильные" результаты.

Ответ 6

Ни C, ни С++ никогда не выполняют никаких арифметических операций над типами, меньшими, чем int. Каждый раз, когда вы указываете меньший операнд (любой аромат char или short), операнд получает статус int или unsigned int, в зависимости от диапазона.