Неявные правила преобразования типов в операторы С++
Я хочу лучше узнать, когда я должен бросить. Каковы правила неявного преобразования типов в С++ при добавлении, умножении и т.д. Например,
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
et cetera...
Будет ли выражение всегда оцениваться как более точный тип? Различаются ли правила для Java?
Пожалуйста, поправьте меня, если я сформулирую этот вопрос неточно.
Ответы
Ответ 1
В С++ операторы (для типов POD) всегда действуют на объекты того же типа.
Таким образом, если они не будут одинаковыми, они будут повышены в соответствии с другими.
Тип результата операции совпадает с типом операндов (после преобразования).
If either is long double the other is promoted to long double
If either is double the other is promoted to double
If either is float the other is promoted to float
If either is long long unsigned int the other is promoted to long long unsigned int
If either is long long int the other is promoted to long long int
If either is long unsigned int the other is promoted to long unsigned int
If either is long int the other is promoted to long int
If either is unsigned int the other is promoted to unsigned int
If either is int the other is promoted to int
Both operands are promoted to int
Примечание. Минимальный размер операций int
. Таким образом, short
/char
продвигается до int
до выполнения операции.
Во всех ваших выражениях int
продвигается до float
до выполнения операции. Результатом операции является float
.
int + float => float + float = float
int * float => float * float = float
float * int => float * float = float
int / float => float / float = float
float / int => float / float = float
int / int = int
int ^ float => <compiler error>
Ответ 2
Арифметические операции с float
приводят к float
.
int + float = float
int * float = float
float * int = float
int / float = float
float / int = float
int / int = int
Подробнее. Посмотрите, что говорится в разделе §5/9 стандарта С++.
Многие бинарные операторы, которые ожидают операнды арифметики или перечисления тип вызывает конверсии и доходность аналогичным образом. Цель состоит в том, чтобы дать общий тип, , который также является типом результата.
Этот шаблон называется обычным арифметические преобразования, которые определяется следующим образом:
- Если один из операндов имеет тип long двойной, другой должен быть преобразован длинный двойной.
- В противном случае, если операнд двойной, другой должен быть преобразован в двойной.
- В противном случае, если либо операндом является float, другой преобразуется в float.
- В противном случае интегральные акции (4.5) должны выполняться на обоих операнды .54)
- Тогда, если либо операнд долгое время без знака преобразуется в unsigned long.
- В противном случае, если один операнд длинный int и другой неподписанный int, тогда если длинный int может представлять все значения беззнакового int, unsigned int преобразуется в long int; в противном случае оба операнда должны быть преобразованы в unsigned long внутр.
- В противном случае, если любой из операндов долго, другой должен быть преобразован в долго.
- В противном случае, если либо операнд является неподписанным, другое должно быть преобразован в unsigned.
[Примечание: в противном случае единственным оставшимся случаем является что оба операнда являются int]
Ответ 3
Поскольку другие ответы не говорят о правилах в С++ 11, здесь один. Из стандарта С++ 11 (черновик №3337) §5/9 (подчеркнуто отличие):
Этот шаблон называется обычными арифметическими преобразованиями, которые определяются следующим образом:
- если какой-либо из операндов имеет тип перечисления с ограниченным диапазоном, преобразования не выполняются; если другой операнд не имеет того же типа, выражение неправильно сформировано.
- Если один из операндов имеет тип long double, другой должен быть преобразован в long double.
- В противном случае, если один из операндов является двойным, другой должен быть преобразован в двойной.
- В противном случае, если один из операндов является float, другой должен быть преобразован в float.
- В противном случае интегральные продвижения выполняются для обоих операндов. Затем к повышенным операндам применяются следующие правила:
- Если оба операнда имеют одинаковый тип, дальнейшее преобразование не требуется.
- В противном случае, если оба операнда имеют целочисленные типы со знаком или оба имеют целочисленные типы без знака, операнд с типом меньшего целого ранга преобразования должен быть преобразован в тип операнд с большим рангом.
- В противном случае, если операнд с целочисленным типом без знака имеет ранг, больший или равный ранг типа другого операнда, операнд со знаком целого типа должен быть преобразован в тип операнда с целым типом без знака.
- В противном случае, если тип операнда с целочисленным типом со знаком может представлять все значения типа операнда с целочисленным типом без знака, операнд с целочисленным типом без знака должен быть преобразован в тип операнда со знаком целого типа.
- В противном случае оба операнда должны быть преобразованы в целочисленный тип без знака, соответствующий тип операнда со знаком целого типа.
Смотрите здесь для списка, который часто обновляется.
Ответ 4
Этот ответ во многом определяется комментарием @RafałDowgird:
"Минимальный размер операций - int". - Это было бы очень странно (что относительно архитектур, которые эффективно поддерживают char/short операции?) Действительно ли это в спецификации С++?
Имейте в виду, что стандарт С++ имеет всеохватывающее правило "как есть". См. Раздел 1.8: Выполнение программы:
3) Это положение иногда называют правилом "как есть", поскольку реализация может свободно игнорировать любые требования Стандарта до тех пор, пока результат будет таким, как если бы требование было соблюдено, насколько это возможно как это можно определить из наблюдаемого поведения программы.
Компилятор не может установить размер int
размером 8 бит, даже если он был самым быстрым, так как в стандарте содержится минимум 16 бит int
.
Следовательно, в случае теоретического компьютера с сверхбыстрыми 8-битными операциями может иметь значение неявное продвижение до int
для арифметики. Однако для многих операций вы не можете определить, действительно ли компилятор выполнял операции с точностью int
, а затем преобразовывался в char
для хранения в вашей переменной или если операции выполнялись в char все время.
Например, рассмотрим unsigned char = unsigned char + unsigned char + unsigned char
, где добавление будет переполняться (допустим, чтобы значение 200 для каждого). Если вы повысились до int
, вы получите 600, что затем будет неявно опущено в unsigned char
, которое будет обертывать по модулю 256, что даст окончательный результат 88. Если вы не сделали таких рекламных акций, вы бы должны обернуться между первыми двумя дополнениями, что уменьшит проблему с 200 + 200 + 200
до 144 + 200
, что составляет 344, что уменьшится до 88. Другими словами, программа не знает разницы, поэтому компилятор свободен для игнорировать мандат на выполнение промежуточных операций в int
, если операнды имеют более низкий рейтинг, чем int
.
Это вообще относится к сложениям, вычитанию и умножению. Это не верно в общем случае для деления или модуля.
Ответ 5
Если вы исключаете неподписанные типы,
иерархия: подписан char, короткий, int, long, long long, float,
двойной, длинный двойной. Во-первых, все, что приходит перед int в
выше будет преобразован в int. Затем, в двоичной операции,
более низкий ранжированный тип будет преобразован в более высокий, а
результаты будут типом высшего. (Вы заметите, что из
иерархия, в любое время с плавающей точкой и интегральным типом
участвующий, интегральный тип будет преобразован в плавающий
точечный тип.)
Unsigned немного усложняет ситуацию: он нарушает рейтинг и
части ранжирования становятся реализацией. Из-за
это, лучше не смешивать подписанные и неподписанные в одном и том же
выражение. (Большинство экспертов на C++, похоже, избегают
побитовые операции. То есть, по крайней мере, что
Страуструп рекомендует.)
Ответ 6
My решение в problem получил WA (неправильный ответ), то я изменил один из int
на long long int
и дал AC (accept). Раньше я пытался сделать long long int += int * int
, и после того, как исправил его до long long int += long long int * int
. Googling я придумал,
Условия преобразования типов:
Условия Met --- > Конверсия
-
Оба операнда имеют тип длинный двойной. --- > Другой операнд преобразуется в тип длинный двойной.
-
Предыдущее условие не выполнено, и оба операнда имеют тип double. --- > Другой операнд преобразуется в тип double.
-
Предыдущие условия не выполняются, и оба операнда имеют тип float. --- > Другой операнд преобразуется в тип float.
-
Предыдущие условия не выполняются (ни один из операндов не имеет плавающих типов). --- > Интегральные рекламные акции выполняются по операндам следующим образом:
- Если любой из операндов имеет тип unsigned long, другой операнд преобразуется в тип без знака long.
- Если предыдущее условие не выполнено, и если один из операндов имеет тип long, а другой тип unsigned int, оба операнда преобразуются в тип без знака.
- Если предыдущие два условия не выполняются, и если один из операндов имеет тип long, другой операнд преобразуется в тип long.
- Если предыдущие три условия не выполняются и если один из операндов имеет тип unsigned int, другой операнд преобразуется в тип unsigned int.
- Если ни одно из предыдущих условий не выполняется, оба операнда преобразуются в тип int.
Целочисленные типы, меньшие, чем int, продвигаются, когда на них выполняется операция. Если все значения исходного типа могут быть представлены как int, значение меньшего типа преобразуется в int; в противном случае он преобразуется в unsigned int. Целочисленные акции применяются как часть обычных арифметических преобразований к некоторым выражениям аргументов; операнды унарных +, - и ~ операторов; и операнды операторов сдвига.
Ответ 7
Тип выражения, когда обе части одного типа одного типа, будет преобразован в самый большой из них. Проблема здесь в том, чтобы понять, какая из них больше, чем другая (она не имеет ничего общего с размером в байтах).
В выражениях, в которых задействовано действительное число и целое число, целое число будет увеличено до действительного числа. Например, в int + float тип выражения float.
Другое отличие связано с возможностью типа. Например, выражение, включающее int и long int, будет иметь тип long long.
Ответ 8
Целая глава 4 рассказывает о конверсиях, но я думаю, вы должны быть в основном заинтересованы в них:
4.5 Интегральные акции
[Conv.prom]
Rvalue типа char, подписанный char, unsigned char, short int или unsigned short
int может быть преобразован в rvalue типа int, если int может представлять все значения типа источника;
Другие-
мудрый, исходное значение rvalue может быть преобразовано в rvalue типа unsigned int.
Rvalue типа wchar_t (3.9.1) или тип перечисления (7.2) можно преобразовать в значение r первого
следующих типов, которые могут представлять все значения его базового типа: int, unsigned int,
долго или без знака.
Rvalue для целочисленного битового поля (9.6) можно преобразовать в r-значение типа int, если int может представлять все
значения битового поля; в противном случае он может быть преобразован в unsigned int, если unsigned int может отображаться
resent все значения бит-поля. Если бит-поле еще больше, к нему не применяется целая реклама. Если
бит-поле имеет нумерованный тип, он рассматривается как любое другое значение этого типа для целей продвижения.
Rvalue типа bool может быть преобразовано в rvalue типа int, при этом false становится нулевым и истинным
становится одним.
Эти преобразования называются интегральными акциями.
4.6 Плавающая точка продвижения
[Conv.fpprom]
Rvalue типа float может быть преобразовано в rvalue типа double. Значение не изменяется.
Это преобразование называется продвижением с плавающей запятой.
Следовательно, все преобразования, включающие float - результат - float.
Только тот, который включает оба int - результат: int:
int/int = int
Ответ 9
Протест!
Конверсии происходят слева направо.
Попробуйте следующее:
int i = 3, j = 2;
double k = 33;
cout << k * j / i << endl; // prints 22
cout << j / i * k << endl; // prints 0