Программирование на Objective-C 2.0
Шрифт:
Если для w1 и w2 заданы соответственно шестнадцатеричные значения 5е и d6, то операция исключающего ИЛИ, примененная к w1 и w2, даст в результате шестнадцатеричное значение е8, как показано ниже. w1 0000 0000 0101 1110 0х5е w2 0000 0000 1011 0110 ^ 0xd6 --------------------------------------- 0000 0000 1110 1000 0хе8 Оператор дополнения до единицы
Оператор дополнения до единицы (ones complement) — это унарный оператор, который меняет биты операнда на противоположные. Каждый бит, равный 1, изменяется на 0, и каждый бит, равный 0, изменяется на 1. Таблица истинности приводится здесь просто для полноты изложения. b1 ~b1 0 1 1 0
Если
Операцию дополнения до единицы полезно использовать, если вы не знаете размера в битах значения, к которому применяется какая-либо операция, и его использование может сделать программу менее зависимой от конкретного размера целого типа данных. Например, чтобы задать значение 0 для младшего бита переменной w1 типа int, можно применить операцию И к w1 и переменной типа int, содержащей все единицы, за исключением 0 в крайнем правом бите. Следующую строку на С можно применить на машинах, где целое значение представляется 32 битами: w1 &= OxFFFFFFFE;
Если заменить ее следующей строкой, то операция И будет применена к w1 и нужному значению на любой машине. w1 &=~1;
Операция дополнения до единицы, примененная к значению 1, даст 0 в край-нем правом бите, а все остальные биты слева будут равны 1 для значения типа любой длины (31 левый бит для 32-битных целых значений).
Приведем пример конкретной программы, где показано использование раз-личных битовых операторов. // Примеры битовых операторов #import <Foundation/Foundation.h> int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; unsigned int w1 = OxAOAOAOAO, w2 = OxFFFFOOOO, w3 = 0x00007777; NSLog (@"%x %x %x", w1 & w2, w1 | w2, w1 Л w2); NSLog (@"%x %x %x", ~w1, ~w2, ~w3); NSLog (@"%x %x %x", w1 л w1, w1 & ~w2, w1 | w2 | w3); NSLog (@"%x %х", w1 | w2 & w3, w1 | w2 & ~w3); NSLog (@"%x %x", ~(~w1 & ~w2), ~(~w1 | ~w2)); [pool drain]; return 0; }
Вывод программы 4.7 a0a00000 ffffaOaO 5f5fa0a0 5f5f5f5f ffff ffff8888 0 aOaO fffff7f7 aOaOaOaO ffffaOaO ffffaOaO aOaOOOOO
Проработайте каждую из операций программы 4.7, чтобы убедиться, что вы понимаете, как получены результаты.
В четвертом вызове NSLog важно отметить, что побитовый оператор И имеет более высокий приоритет, чем побитовый оператор ИЛИ. Сводку приоритетов операторов см. в приложении В.
В пятом вызове NSLog иллюстрируется правило ДеМоргана: ~(~а & ~Ь) равно а | Ь, и ~(~а | ~Ь) равно а & Ь. Последовательность операторов показывает, что операция обмена действует так, как описано в разделе по оператору исключающего ИЛИ. Оператор левого сдвига
Если к значению применяется операция левого сдвига, то биты этого значения буквально сдвигаются влево. Для этой операции указывается число позиций (битов), на которое должно быть сдвинуто значение. Биты, которые выходят за старший бит элемента данных, утрачиваются, а младшие биты значения заме-щаются нулями. Например, если значение w1 равно 3, то выражение w1 = w1 << 1;
которое можно также представить как w1 <<= 1;
даст в результате смещение 3 на одну позицию влево, то есть w1 будет присвоено значение 6: w1 ...00000011 0x03 w1 << 1 ...00000110 0x06
Операнд слева от оператора « — это значение, к которому применяется сдвиг, а оператор справа — это количество битовых позиций, на которое
Как следует из этого названия, оператор правого сдвига » смещает биты значения вправо. Биты, смещаемые за позицию младшего бита, теряются. Смещение вправо значения без знака (unsigned) приводит к замещению нулями старших битов. Замещение левой позиции для значений со знаком (signed) зависит от знака смещаемого вправо значения, а также от реализации этой операции в вашей компьютерной системе. Если бит знака равен 0 (для положительного значения), то происходит замещение нулями независимо от используемой машины. Но если бит знака равен 1, то на некоторых машинах происходит замещение единицами, а на других машинах — нулями. Первый тип операции называется арифметическим правым сдвигом, а второй тип — логическим правым сдвигом.
Внимание. Никогда не делайте предположений о типе правого сдвига (арифме-тическом или логическом), реализуемом в вашей системе. Программа, которая выполняет правый сдвиг значений со знаком, может работать правильно на одном компьютере и давать сбой на другом.
Если переменная w1 имеет тип unsigned int, представленный 32 битами, и w1 присвоено шестнадцатеричное значение F777EE22, то смещение w1 на одну по-зицию вправо с помощью оператора w1 >>= 1;
даст в результате шестнадцатеричное значение 7BBBF711, как показано ниже. w1 1111 0111 0111 0111 1110 1110 0010 0010 0xF777EE22 w1 >> 1 0111 1011 1011 1011 1111 0111 0001 0001 0x7BBBF711
Если w1 объявлена как (signed) short int, то на некоторых компьютерах будет получен тот же результат, а на других будет получено значение FBBBF711, если операция выполняется как арифметический правый сдвиг.
Если выполняется сдвиг значения влево или вправо на число позиций, равное или превышающее количество бит этого значения, то Objective-C не дает определенный результат. Например, на машине, представляющей целое значение 32 битами, сдвиг целого значения влево или вправо на 32 или больше битов не обязательно даст определенный результат. Если указана отрицательная величина смещения, то результат тоже неопределенный. 4.6. Типы: _Bool, .Complex и .Imaginary
Завершая эту главу, упомянем еще три типа: _Bool, для работы с булевыми зна-чениями (0 или 1), .Complex и .Imaginary — для работы с комплексными и мнимы-ми числами соответственно.
Программисты Objective-C обычно используют тип данных B00L вместо .Bool для работы с булевыми значениями. В действительности это не тип данных, а еще одно имя для типа данных char. Его определяют с помощью специального ключевого слова typedef, которое описывается в главе 10. Упражнения
Какие из следующих констант являются недопустимыми? Почему? 123.456 0x10.5 0X0G1 0001 OxFFFF 123L 0ХаЬО5 0L -597.25 123.5е2 .0001 +12 98.6F 98.7U 17777s 0996 -12Е-12 07777 1234uL 1.2Fe-7 15,000 1.234L 197u 100U OXABCDEFLOxabcu +123
Напишите программу, которая преобразует 27° по Фаренгейту (F) в градусы Цельсия (С) с помощью следующей формулы: С = (F - 32) / 1.8
Какой вывод даст следующая программа? #import <Foundation/Foundation.h> int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; char c, d; c = 'd'; d = c; NSLog (@"d = %c", d); [pool drain]; return 0; }
Напишите программу для вычисления полинома. Зх<sup>3</sup> - 5х<sup>2</sup> + 6, для х = 2.55.