Сомнения в поведении смещения битов

Я хотел бы развеять некоторые сомнения по поводу битового сдвига:

  1. Использование unsigned int:

    unsigned int i = 500;
    i << 24;

    Насколько мне известно, это вызывает переполнение unsigned int, это нормально?

C ++ 17 (8.5.7 / 2) - Значение E1 ‹---------------- E2 - битовые позиции E2 со смещением влево E1; освобожденные биты заполняются нулями. Если E1 имеет беззнаковый тип, значение результата будет E1 × 2 ^ E2, уменьшенное по модулю на единицу больше, чем максимальное значение, представленное в типе результата.

  1. Использует правый сдвиг на signed int отлично, пока я смещаю менее 32 бит, потому что int на моей платформе 32 бита.

    int i = 500;
    i >> 31;

Это переполнение?

C ++ 17 (8.5.7 / 3) Значение E1 >> E2 - это E1, сдвинутые вправо битовые позиции E2. Если E1 имеет беззнаковый тип или если E1 имеет знаковый тип и неотрицательное значение, значение результата является неотъемлемой частью частного E1 / 2 ^ E2.


person user963241    schedule 25.05.2019    source источник
comment
unsigned переполнения нет. Когда произойдет переполнение для значения unsigned, число уменьшается по модулю на наибольшее значение для типа + 1. Имеется signed переполнение.   -  person David C. Rankin    schedule 25.05.2019


Ответы (1)


  1. # P1 #
    # P2 #
  2. # P3 #
    # P4 #

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

person geza    schedule 25.05.2019
comment
Он также не определен, если вы сдвигаете влево отрицательное значение или если сдвиг влево положительного значения со знаком переполняется. - person interjay; 25.05.2019
comment
@interjay: вы имеете в виду, в текущем проекте стандарта? (Я говорю о текущем драфте там) - person geza; 25.05.2019
comment
Означает ли это, что в C ++ 17 сдвиг вправо для положительного signed целого числа четко определен? Я полагаю, что сдвиг влево для положительного целого числа со знаком - нет, если значение не представляется возможным. - person user963241; 25.05.2019
comment
Я говорю о последнем выпущенном стандарте C ++ 17 (который помечен как вопрос). Не знаю, изменилось ли что-то в последнем проекте. - person interjay; 25.05.2019
comment
Означает ли это, что в C ++ 17 сдвиг вправо положительного целого числа со знаком четко определен? да. Я полагаю, что сдвиг влево для положительного целого числа со знаком - нет, если значение не представимо. Это только UB, если результат не может быть представлен в беззнаковой версии. Итак, сдвиг в знаковый бит - это нормально (определяется реализацией), но сдвиг на большее - нет. Но эти правила больше не имеют большого значения, поскольку следующий проект их упростил, так как для этого потребуется два дополнительных числа. - person geza; 25.05.2019
comment
@interjay: это, скорее всего, изменится, я об этом и говорю, я даже ссылку туда поместил. Но я немного расширил свою заметку, чтобы быть более ясным. - person geza; 25.05.2019
comment
@geza: Означает ли это, что нет целочисленного переполнения для целого числа со знаком, когда используется правый сдвиг, потому что результат оборачивается вокруг? (C ++ 17) - person user963241; 25.05.2019
comment
@ user963241: Я вас не совсем понимаю. Сдвиг вправо - это операция, подобная делению. Как вы думаете, почему это вызывает переполнение? Это может только уменьшить значение. Когда мы говорим о переполнении, это означает, что значение настолько велико (по величине), что не вписывается в тип результата. - person geza; 25.05.2019
comment
@geza: Хорошо, понятно, я использовал это определение вики: an integer overflow occurs when an arithmetic operation attempts to create a numeric value that is outside of the range that can be represented with a given number of digits – either larger than the maximum or lower than the minimum representable value. оно также включает минимальное представимое значение. - person user963241; 25.05.2019
comment
@ user963241: да, но сдвиг вправо всегда уменьшает (или не меняет) значение (по величине). Так, например, 8>>1==4, -8>>1==-4 (сдвиг вправо отрицательного значения определяется реализацией в C ++ 17, но не в текущем проекте). Невозможно, чтобы сдвиг вправо вызвал переполнение. Думайте о >> как о делении с той небольшой разницей, что при целочисленном делении округляется до нуля, а при >> округляется в меньшую сторону (для положительных чисел они одинаковы, для отрицательных могут отличаться). - person geza; 25.05.2019