Так что это, вероятно, действительно простой вопрос, и если бы речь шла не о C++, я бы просто проверил, работает ли он на моем компьютере или нет, но, к сожалению, в C++ вещи обычно работают на нескольких системах, оставаясь при этом UB и поэтому не работает в других системах.
Рассмотрим следующий фрагмент кода:
unsigned long long int a = std::numeric_limits< unsigned long long int >::max();
unsigned int b = 12;
bool test = a > b;
Мой вопрос: можем ли мы сравнивать целые числа разного размера друг с другом без явного преобразования меньшего типа в больший, например, static_castбез работает с неопределенным поведением (UB)?
В общем, я могу представить себе это тремя способами:
Это подпадает под правила целочисленное продвижение. Нет UB.
См. Также раздел, в котором применяются преобразования для арифметические операторы
Как сказано в ответе @NathanPierson, ваш пример будет работать, но будьте осторожны, если вы смешиваете подписанный и неподписанный (простой совет - не делайте этого).
Совет: если применимо (как здесь), вы можете проверить, если что-то является UB, запустив его в функции constexpr во время компиляции (убедившись, что действительно принудительно выдает результат времени компиляции) и проверив, вызывает ли это ошибку компилятора. Под применимым я подразумеваю код разрешается для запуска во время компиляции (так что без исключений, без asm, без reinterpret_cast и т. д.) Вот простой пример проверки разыменования нулевого указателя.
@chris ах да, это действительно правда. Спасибо что подметил это. Я буду использовать этот трюк в будущем!





Это безопасно. C++ имеет то, что называется Обычные арифметические преобразования, и они обрабатывают то, как неявно преобразовывать объекты, переданные во встроенные бинарные операторы.
В этом случае происходит целочисленное продвижение, и b конвертируется для вас в unsigned long long int, а затем оценивается operator >.
Это не неопределенное поведение. Это покрывается обычные арифметические преобразования, которые подробно описаны в разделе 8p11.5 Стандарт C++ 17:
The integral promotions (7.6) shall be performed on both operands. Then the following rules shall be applied to the promoted operands:
- (11.5.1) If both operands have the same type, no further conversion is needed.
- (11.5.2) Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand with greater rank.
- (11.5.3) Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.
- (11.5.4)Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type.
- (11.5.5)Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.
Здесь применяется отрывок, выделенный жирным шрифтом. Поскольку оба типа беззнаковые, меньший тип преобразуется в больший, так как формат может содержать подмножество значений, которые последний может содержать.
Не UB. Google для "целочисленного продвижения C++"