Может ли целое число без знака активировать поведение undefined?

Изменить: Изменено значение для USHRT_MAX, поскольку оно не соответствует, как показано комментариями.


Представьте, что у вас есть фантастический компилятор, где его ограничения типа integer, как определено в limits.h, следующие:

#define INT_MAX   2147483647   /* Typical 32-bit system value */
#define USHRT_MAX 2147483647   /* ***Edited***, original question had 2000000000 */

И в моем приложении у меня есть следующий код:

unsigned short a = 1500000000;
unsigned short b = 1500000000;
unsigned short c;
c = a + b;

Насколько я знаю, что произойдет в последней инструкции:

  • Интегральное продвижение по a. Поскольку int может принимать все значения unsigned short, a получает повышение до int.
  • По тем же причинам b получает повышение до int.
  • Дополнение происходит на типах int.
  • Результат не представлен в int. Undefined Поведение в соответствии с пунктом 6.5/5.

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

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

Ответ 1

Может ли целое число без знака вызывать поведение undefined?

Это зависит.

Если

  • ранг a int больше, чем два операнда, о которых идет речь (unsigned short int здесь, поэтому в этом случае это верно) и
  • значения двух соответствующих операндов будут вписываться в int (важный угловой случай, если не * 1) и
  • арифметическая операция (добавление здесь) будет переполняться

то да, это вызовет UB.

Причины:

  • Операнды, о которых идет речь (unsigned short intздесь), получают арифметические операции до int (они не будут в случае * 1).
  • Переполнение арифметических операций на int вызывает UB.

* 1: Если операнд не вписывается в int, он получает повышение до unsigned int, и при этом любая арифметическая операция в соответствии с 2. выше будет not вызывать UB.

Ответ 2

Невозможно определить USHRT_MAX как 2000000000. Максимальные значения целых чисел без знака должны быть в форме: 2 ^ n-1:

6.2.6.2 Целочисленные типы

  • Для беззнаковых целочисленных типов, отличных от unsigned char, биты объекта представление делится на две группы: биты значений и биты заполнения (необходимо не быть последним). Если бит N значений бит, каждый бит должен представлять собой мощность 2 между 1 и 2 N-1, чтобы объекты такого типа были способны представляющие значения от 0 до 2 N - 1, используя чисто двоичное представление; это должно быть известный как представление значения. Значения любых битов дополнений не определены.

Скажем, USHRT_MAX составляет 2 ^ 31-1, а INT_MAX - 2 ^ 31-1.

В этом случае переменным a и b будет присвоен тип int, из-за целых рекламных акций, и результат подписанного сложения будет переполняться.

gcc достаточно умен, чтобы обрабатывать добавление двух неподписанных коротких переменных как unsigned, когда они назначены на unsigned short.

Тем не менее, для полной переносимости код должен быть:

c = a + 0u + b;