Чтобы оптимизировать мой код cpp, в некоторых случаях я пытаюсь использовать смещение вправо. Вот пример:
int main()
{
int i = (1 - 2) >> 31; // sizeof(int) == 4
...
...
}
Я напечатал i и получил -1. Это означает, что он будет использовать 1 вместо 0 для заполнения пустой позиции, если число отрицательное. Другими словами, -1 >> 31 работает следующим образом:
1111...1 <--- the result of (1 - 2), which is -1
1111...1 <--- -1 >> 31, 1 is used to fill in the empty position
Я просто хочу знать, четко ли определено это поведение или нет?
Если это UB в cpp, то как насчет Java?
Ответ 1 · рейтинг 1 · msc
Да. Это определяется реализацией.
Согласно C++03 5.8/3, который определяет сдвиг вправо:
Значение E1 >> E2 - это E1, сдвинутая вправо E2 битовых позиций. Если E1 имеет беззнаковый тип или если E1 имеет знаковый тип и неотрицательное значение, значение результата равно целой части частного E1, деленной на число 2, возведенное в степень E2. Если E1 имеет тип со знаком и отрицательное значение, результирующее значение определяется реализацией.
Для получения дополнительной информации см. этот ссылка.
Ответ 2 · рейтинг 1 · SAI ESWAR
По умолчанию он подписан int. Диапазон от -32767 до 32767, побитовый диапазон от -111111111111111 до +111111111111111. Самый первый бит слева действует как отрицательный или положительный индикатор. И все арифметические операции будут выполняться методом дополнения до 2. В общем, отрицательный int представлен в методе двух дополнений, т.е. возьмем пример того, как представлен -1.
4 Bytes = 32 bits
0000 0000 0000 0000 0000 0000 0000 0000
how represent 1
0000 0000 0000 0000 0000 0000 0000 0001
Then we invert the digits. 0 becomes 1, 1 becomes 0.
1111 1111 1111 1111 1111 1111 1111 1110
Then we add 1.
1111 1111 1111 1111 1111 1111 1111 1111
This is how -1 is represented
Сдвиг вправо отрицательного числа определяется как сдвиг на 1 с к старшим битовым позициям, тогда в дополнительном представлении на 2 с он будет вести себя как арифметический сдвиг - результат сдвига вправо на N будет таким же, как деление на 2N , округляя в сторону минус бесконечности. Таким образом, смещение -1 равно -1, теперь возьмите другое число. Например, если у вас есть 8-битное двоичное число с дополнением до 2, пусть оно представляет -3
0000 0011
Then we invert the digits.
1111 1100
Then we add 1.
1111 1101
11111101, представляющее -3 в десятичном виде, и вы выполняете арифметический сдвиг вправо на 1, чтобы получить 11111110, представляющий -2 в десятичном виде, это то же самое, что и деление -3 на 2 ^ 1, что дает -1,5, которое округляется до отрицательной бесконечности, что приводит к -2 .
Ответ 3 · Andreas
В Java поведение >> четко определено для отрицательных чисел (см. ниже).
В C++ поведение >> не определено для отрицательных чисел (см. ответ от rsp а>).
Цитирование спецификации языка Java, §15.19. Операторы смены:
Значение n ›› с равно n сдвигу вправо с битовых позиций с расширением знака . Полученное значение равно floor(n / 2s). Для неотрицательных значений n это эквивалентно усечению целочисленного деления, вычисляемого оператором целочисленного деления /, на два в степени s.
Значение n ››› с равно n сдвигу вправо с битовых позиций с нулевым расширение, где:
Если n положительное, то результат будет таким же, как и у n ›› s.
Если n отрицательное и тип левого операнда int, то результат равен результату выражения (n ›› s) + (2 ‹‹ ~s) эм>.
Если n отрицательное и тип левого операнда long, то результат равен результату выражения (n ›› s) + (2L ‹‹ ~s) эм>.