Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
49
Добавлен:
12.05.2015
Размер:
1.82 Mб
Скачать

Глава 4. Операции 95_

Когда значение имеет биты, которые "выдвигаются" (в данном случае — вправо), такие биты теряются. Например, следующий кодовый фрагмент сдвигает значение 35 вправо на две позиции, что приводит к потере двух младших битов, заканчиваясь снова установкой значения 8.

int a = 35;

а = а » 2; // снова содержит 8

Взгляд на ту же операцию в двоичном представлении яснее показывает, как это происходит:

00100011 (35)

» 2

00001000 (8)

Каждый раз, когда вы сдвигаете значение вправо, оно делится на два и от­брасывает любой остаток. Этим можно воспользоваться для высокоэффек­тивного целочисленного деления на 2. Конечно, вы должны убедиться, что не выдвигаете никакие биты с правого конца.

При сдвиге вправо старшие (крайние левые) биты освобождаются и запол­няются предыдущим содержимым старшего (знакового) бита. Это так назы­ваемое расширение знака. Оно служит для того, чтобы сохранить знак отри­цательных чисел, когда вы сдвигаете их вправо. Например, —8 ».1 дает —4, что в двоичной форме выглядит так:

11111000 (-8)

»1

11111100 (-4)

Интересно обратить внимание, что, если вы сдвигаете —1 вправо, результат всегда остается — 1, так как расширение знака продолжает вводить все боль­ше единиц в старшие биты.

Иногда расширение знака при сдвиге значений вправо не желательно. На­пример, следующая программа преобразует byte-значение к его шестнад-цатеричному строчному представлению. Заметим, что сдвинутое значение маскируется выполнением операции (Ь » 4) & OxOf, чтобы отказаться от любых расширенных знаком битов (это делается для того, чтобы значение могло использоваться как индекс в массиве шестнадцатеричных символов).

// Маскировка расширения знака, class HexByte {

static public void main(String args[]} { char hex[] = {

I [Л I I -] I 10? I Q I ? Л I IRI I fLI I -7 I

U , L , Z, О / Ч, Э , . О / /,

'8', '9', 'a1, 'b', 'c', 'd', '&', 'f }; byte b = (byte) Oxfl;

96 Часть I. Язык Java

System.out.println("b = Ox" + hex[(b » 4) & OxOf] + hex[b & OxOf]); } }

Вывод этой программы:

b = Oxfl

Вывод этой программы:

b = Oxfl

Правый сдвиг без знака

Как вы только что видели, операция » автоматически наполняет старший бит его предыдущим содержанием каждый раз, когда происходит сдвиг. Это сохраняет знак числа. Правда, иногда это не желательно. Например, если вы сдвигаете что-то, что не представляет числового значения, вы можете не хо­теть расширения знака. Эта ситуация обычно имеет место, когда вы рабо­таете с пикселными значениями и графикой. В этих случаях вы вообще за­хотите поместить нуль в старший бит, независимо от того, каково было его начальное значение. Такая процедура известна как беззнаковый сдвиг. Чтобы выполнить ее, нужно использовать Java-операцию беззнакового сдвига вправо >», которая всегда вставляет нуль в старший бит.

Следующий кодовый фрагмент демонстрирует операцию >». Здесь пере­менная а установлена в — 1, что устанавливает все 32 бита ее двоичного представления в 1. Затем это значение сдвигается вправо на 24 бита, запол­няя 24 верхних бита нулями и игнорируя нормальное расширение знака. Это устанавливает в а значение 255.

int a = -1; а = а >» 24;

Чтобы проиллюстрировать, что происходит, ниже показана та же операция в двоичной форме:

11111111 11111111 11111111 11111111 (-1 в двоичной форме типа int)

>»24

00000000 00000000 00000000 11111111 (255 в двоичной форме типа int)

Операция >» часто не столь полезна, как вам бы хотелось, т. к. она значима только для 32- и 64-разрядных значений. Напомним, что меньшие значения в выражениях автоматически расширяются до int. Это означает, что проис­ходит расширение знака, и что сдвиг будет иметь место скорее на 32-раз­рядном, чем на 8- или 16-разрядном значении. То есть, можно ожидать, что беззнаковый правый сдвиг на byte-значении заполнит нулем все разряды, начиная с седьмого. Но дело обстоит не так, поскольку фактически сдви­гается 32-разрядное значение. Следующая программа демонстрирует этот эффект:

Соседние файлы в папке JavaLit