Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Сдвиг вправо без учета знака. Побитовые составные операции с присваиванием. Операции сравнения




Сдвиг вправо без учета знака

Как было показано, при каждом выполнении операция > > автоматически заполняет старший бит его предыдущим содержимым. В результате знак значения сохраняется.

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

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

знаковых разрядов. В результате значение a становится равным 255.

int a = -1;

a = a > > > 24;

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

11111111 11111111 11111111 11111111 –1 в двоичном представлении типа int > > > 24

00000000 00000000 00000000 11111111 255 в двоичном представлении типа int

Часто операция > > > не столь полезна, как хотелось бы, поскольку она имеет смысл только для 32- и 64-разрядных значений. Помните, что в выражениях тип меньших значений автоматически повышается до int. Это означает применение дополнительных знаковых разрядов и выполнение сдвига по отношению к 32-разрядным, а не 8- или 16-разрядным значениям. То есть программист может подразумевать выполнение сдвига вправо без учета знака применительно к значению типа byte и заполнение нулями, начиная с бита 7.

Однако в действительности это не так, поскольку фактически сдвиг будет выполняться в 32-разрядном значении. Этот эффект демонстрирует следующая программа.

// Сдвиг без учета знака значения типа byte.

class ByteUShift {

static public void main(String args[]) {

char hex[] = {

'0', '1', '2', '3', '4', '5', '6', '7',

'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'

};

byte b = (byte) 0xf1;

byte c = (byte) (b > > 4);

byte d = (byte) (b > > > 4);

byte e = (byte) ((b & 0xff) > > 4);

System. out. println(" b = 0x"

+ hex[(b > > 4) & 0x0f] + hex[b & 0x0f]);

System. out. println(" b > > 4 = 0x"

+ hex[(c > > 4) & 0x0f] + hex[c & 0x0f]);

System. out. println(" b > > > 4 = 0x"

+ hex[(d > > 4) & 0x0f] + hex[d & 0x0f]);

System. out. println(" (b & 0xff) > > 4 = 0x"

+ hex[(e > > 4) & 0x0f] + hex[e & 0x0f]);

}

}

Из следующего вывода этой программы видно, что операция > > > не выполняет никаких действий по отношению к значениям типа byte. Для этого примера в качестве значения переменной b было выбрано произвольное отрицательное значение типа byte. Затем переменной c присваивается значение переменной b типа byte, сдвинутое вправо на четыре позиции, которое в связи с применением дополнительных знаковых разрядов равно 0xff. Затем переменной d присваивается значение переменной b типа byte, сдвинутое вправо на четыре позиции без учета знака, которым должно было бы быть значение 0x0f, но в действительности, из-за применения дополнительных знаковых разрядов во время повышения типа b до int перед выполнением сдвига, равное 0xff. Последнее выражение устанавливает значение переменной e равным значению типа byte переменной b, замаскированному до 8 бит с помощью операции AND и затем сдвинутому вправо на четыре позиции, что дает ожидаемое значение, равное 0x0f. Обратите внимание, что операция сдвига вправо без учета знака не применялась к переменной d, поскольку состояние знакового бита после выполнения операции AND было известно.

b = 0xf1

b > > 4 = 0xff

b > > > 4 = 0xff

(b & 0xff) > > 4 = 0x0f

Побитовые составные операции с присваиванием

Подобно алгебраическим операциям, все двоичные побитовые операции имеют составную форму, которая объединяет побитовую операцию с операцией присваивания.

Например, следующие два оператора, выполняющие сдвиг вправо на четыре позиции в значении переменной a, эквивалентны:

a = a > > 4;

a > > = 4;

Аналогично, эквивалентны и следующие два оператора, которые присваивают переменной a результат выполнения побитовой операции a OR b:

a = a | b;

a |= b;

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

class OpBitEquals {

public static void main(String args[]) {

int a = 1;

int b = 2;

int c = 3;

a |= 4;

b > > = 1;

c < < = 1;

a ^= c;

System. out. println(" a = " + a);

System. out. println(" b = " + b);

System. out. println(" c = " + c);

}

}

Эта программа создает следующий вывод:

a = 3

b = 1

c = 6

Операции сравнения

Операции сравнения определяют отношение одного операнда с другим. В частности, они определяют равенство и порядок следования.

· == Равно

·! = Не равно

· > Больше

· < Меньше

· > = Больше или равно

· < = Меньше или равно

Результат выполнения этих операций – значение типа boolean. Наиболее часто операции сравнения используют в выражениях, которые управляют оператором if и различными операторами цикла.

В Java можно сравнивать значения любых типов, в том числе целые значения, значения с плавающей точкой, символы и булевские значения, используя проверку равенства == и проверку неравенства! =. Обратите внимание, что Java равенство обозначают двумя знаками “равно”, а не одним. (Одиночный знак “равно” – символ операции присваивания. ) Сравнение с помощью операций упорядочения применимо только к числовым типам. То есть сравнение для определения того, какой из операндов больше или меньше другого, можно выполнять только для целочисленных операндов, операндов с плавающей точкой или символьных операндов.

Как уже было отмечено, результат выполнения операции сравнения представляет собой значение типа boolean. Например, следующий фрагмент кода вполне допустим:

int a = 4;

int b = 1;

boolean c = a < b;

В данном случае результат выполнения операции a < b (который равен false) сохраняется в переменной c.

Те читатели, которые знакомы с языками C/C++, должны обратить внимание на следующее. В программах на C/C++ следующие типы операторов встречаются очень часто:

int done;

//...

if(! done)... // Допустимо в C/C++

if(done)... // но не в Java.

В Java-программе эти операторы должны быть записаны следующим образом:

if(done == 0)... // Это стиль Java.

if(done! = 0)...

Это обусловлено тем, что в Java определение значений “истинно” и “ложно” отличается от их определений в языках C/C++. В C/C++ истинным считается любое ненулевое значение, а ложным – ноль. В Java значения true (истинно) и false (ложно) – нечисловые значения, которые никак не сопоставимы с нулевым или ненулевым значением.

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

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...