Является ли сдвиг влево (<<) отрицательным целочисленным неопределенным поведением в C++ 11?

Сдвиг влево отрицательный int Неопределенное поведение в C++11?

Соответствующие Стандартные отрывки здесь взяты из 5.8:

2 / Значение E1 << E2 - это биты E2, сдвинутые влево E1; освобожденные биты заполнены нулями. Если E1 имеет тип без знака, значение результата равно E1 × 2E2, уменьшенное по модулю на единицу больше максимального значения, представляемого в типе результата. В противном случае, если E1 имеет тип со знаком и неотрицательное значение, а E1 × 2E2 представимо в типе результата, то это результирующее значение; в противном случае поведение не определено.

Часть, которая смущает меня:

В противном случае, если E1 имеет тип со знаком и неотрицательное значение, а E1 × 2E2 представимо в типе результата, то это результирующее значение; в противном случае поведение не определено.

Следует ли это интерпретировать как означающее, что любое отрицательное число, сдвигающее влево, является UB? Или это только означает, что если вы LS отрицательный и результат не вписывается в тип результата, то это UB?

Кроме того, в предыдущем пункте говорится:

1 / Операторы сдвига << и >> группируются слева направо. shift-выражение: аддитивное выражение shift-выражение << аддитивное выражение shift-выражение >> аддитивное выражение

Операнды должны быть целочисленного или незаданного типа перечисления, и выполняются интегральные преобразования.

Тип результата - тип повышенного левого операнда. Поведение не определено, если правый операнд отрицательный, или больше или равен длине в битах повышенного левого операнда.

Это делает очевидным, что использование отрицательного числа для одного из операндов является UB. Если бы это был UB, чтобы использовать отрицательный для другого операнда, я бы ожидал, что это будет ясно и здесь.

Итак, суть, это:

-1 << 1

Неопределенное поведение?


@Angew предоставил псевдокодовую интерпретацию Standardese, которая кратко выражает одну возможную (вероятную) достоверную интерпретацию. Другие задаются вопросом, действительно ли этот вопрос касается применимости языка "поведение не определено" по сравнению с нашим (Stackru) использованием фразы "неопределенное поведение". Эта редакция предназначена для того, чтобы дать больше разъяснений о том, что я пытаюсь спросить.

@ Angew интерпретация Standardese является:

if (typeof(E1) == unsigned integral)
  value = E1 * 2^E2 % blah blah;
else if (typeof(E1) == signed integral && E1 >= 0 && representable(E1 * 2^E2))
  value = E1 * 2^E2;
else
  value = undefined;

На самом деле этот вопрос сводится к следующему - это правильная интерпретация:

value = E1 left-shift-by (E2)

switch (typeof(E1))
{
case unsigned integral :
  value = E1 * 2^E2 % blah blah;
  break;

case signed integral :
  if (E1 >= 0)
  { 
    if (representable(E1 * 2^E2))
    {
      value = E1 * 2^E2;
    }
    else
    {
      value = undefined;
    }
  }
  break;
}

?

Sidenote, рассматривая это с точки зрения псевдокода, ясно показывает, что интерпретация @Agnew является правильной.

3 ответа

Решение

Да, я бы сказал, что это не определено. Если мы переведем стандартное в псевдокод:

if (typeof(E1) == unsigned integral)
  value = E1 * 2^E2 % blah blah;
else if (typeof(E1) == signed integral && E1 >= 0 && representable(E1 * 2^E2))
  value = E1 * 2^E2;
else
  value = undefined;

Я бы сказал, что причина, по которой они явно относятся к правому операнду, а не к левому, состоит в том, что указанная вами парагрпа (та, что с правым операндом) применяется как к левому, так и к правому сдвигам.

Для левого операнда решение отличается. Сдвиг влево негатива не определен, сдвиг вправо определяется реализацией.

Следует ли это интерпретировать как означающее, что любое отрицательное число, сдвигающее влево, является UB?

Да, поведение не определено, если дано любое отрицательное число. Поведение определяется только тогда, когда выполняются оба следующих условия:

  • число неотрицательно
  • E1 × 2E2 представимо в типе результата

Это буквально то, что "если E1 имеет тип со знаком и неотрицательное значение, а E1 × 2E2 представимо в типе результата, то это и есть результирующее значение; в противном случае поведение не определено", говорит:

if X and Y
  then Z
else U

Ответьте согласно Вопросу:

Вопрос действительно таков:

Можем ли мы приравнять термин "поведение не определено" приравнивается именно к термину "неопределенное поведение".

В настоящее время это означает "неопределенное поведение".

Личный комментарий о ситуации

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

В любом случае формулировка (или объяснение) должна быть ужесточена / расширена, чтобы сделать ее менее двусмысленной.

Другие вопросы по тегам