1629295407-c61bfe4caba98380ea3e7cdae6295416 (846200), страница 20
Текст из файла (страница 20)
При сдвиге влево число удваивается. При сдвиге вправо числоделится пополам. Конечно же, это будет справедливо до тех пор, пока с одного или другогоконца не выдвинутся (и потеряются) значимые биты. Вот пример:// Использование операторов сдвига для// умножения и деления на 2.Глава 4. Операторы97using System;class MultDiv {public static void Main() {int n;n = 10;Console.WriteLine("Значение переменной n: " + n);// Умножаем на 2.n = n << 1;Console.WriteLine("Значение переменной n после n = n * 2: " + n);// Умножаем на 4.n = n << 2;Console.WriteLine("Значение переменной n после n = n * 4: " + n);// Делим на 2.n = n >> 1;Console.WriteLine("Значение переменной n после n = n / 2: " + n);// Делим на 4.n = n >> 2;Console.WriteLine("Значение переменной n после n = n / 4: " + n);}}Console.WriteLine();// Устанавливаем n в исходное состояние.n = 10;Console.WriteLine("Значение переменной n: " + n);// Умножаем на 2, причем 30 раз.n = n << 30; // Увы; данные потеряны.Console.WriteLine("Значение n после сдвига влево на 30 разрядов: " + n);Вот как выглядят результаты выполнения этой программы:Значение переменной n: 10Значение переменной n после n = n * 2: 20Значение переменной n после n = n * 4: 80Значение переменной n после n = n / 2: 40Значение переменной n после n = n / 4: 10Значение переменной n: 10Значение n после сдвига влево на 30 разрядов: -2147483648Обратите внимание на последнюю строку результатов выполнения программы.
Послесдвига числа 10 влево на 30 разрядов (т.е. после умножения на 230) информация будетпотеряна, поскольку значение исходного числа было “выдвинуто” за пределы диапазонапредставления чисел, соответствующего типу int. В данном случае вы видите странноеотрицательное значение, которое получилось в результате попадания98Часть I. Язык C#единицы в старший разряд числа, который для типа int используется в качестве знакового.Вследствие этого число стало интерпретироваться как отрицательное.
Этот примерпоказывает, как необходима осторожность при использовании операторов сдвига дляумножения или деления чисел на 2. (Чтобы вспомнить, чем отличается представлениезначений со знаком от представления значений без знака, обратитесь к главе 3.)Поразрядные составные операторы присваиванияВсе бинарные поразрядные операторы можно успешно объединять с операторомприсваивания, образуя поразрядные составные операторы присваивания. Например,следующие две инструкции присваивают переменной x результат выполнения операцииисключающего ИЛИ (XOR) с операндами x и 127.x = x ^ 127;x ^= 127;Оператор ?Одним из самых замечательных операторов C# является тернарный оператор ?.Оператор ? часто используется для замены определенных типов конструкций if-thenelse.
Оператор ? называется тернарным, поскольку он работает с тремя операторами. Егообщий формат записи имеет такой вид:Выражение1 ? Выражение2 : Выражение3;Здесь Выражение1 должно иметь тип bool. Типы элементов Выражение2 иВыражение3 должны быть одинаковы. Обратите внимание на использование ирасположение двоеточия.Значение ?-выражения определяется следующим образом. ВычисляетсяВыражение1.
Если оно оказывается истинным, вычисляется Выражение2, и результат еговычисления становится значением всего ?-выражения. Если результат вычисления элементаВыражение1 оказывается ложным, значением всего ?-выражения становится результатвычисления элемента Выражение3. Рассмотрим пример, в котором переменной absvalприсваивается абсолютное значение переменной val.absval = val < 0 ? -val : val;// Получаем абсолютное// значение val.Здесь переменной absval присваивается значение переменной val, если онобольше или равно нулю.
Если же значение переменной val отрицательно, переменнойabsval присваивается результат применения к ней операции “унарный минус”, которыйбудет представлять собой положительное значение.Вот еще один пример использования оператора ?. В следующей программевыполняется деление числа 100 на разные числа, но попытка деления на нуль реализованане будет.// способ обойти деление на нуль с помощью оператора ?using System;class NoZeroDiv {public static void Main() {int result;int i;Глава 4.
Операторы99}}for(i = -5; i < 6; i++) {result = i != 0 ? 100 / i : 0;if(i != 0)Console.WriteLine("100 / " + i + " равно " + result);}Посмотрите на результаты выполнения этой программы./ -5 равно -20/ -4 равно -25/ -3 равно -33/ -2 равно -50/ -1 равно -100/ 1 равно 100/ 2 равно 50/ 3 равно 33/ 4 равно 25/ 5 равно 20Обратите внимание на следующую строку из этой программы:result - i != 0 ? 100 / i : 0;Здесь переменной result присваивается результат деления числа 100 на значениепеременной i. Однако это деление выполнится только в том случае, если i не равно нулю.В противном случае (при i = 0) переменной result будет присвоено нулевое значение.В действительности совсем не обязательно присваивать переменной значение,генерируемое оператором ?.
Например, вы могли бы использовать это значение в качествеаргумента, передаваемого методу. Или возможен еще такой вариант. Если все выражения,принимаемые оператором ?, имеют тип bool, то результат выполнения этого оператораможно использовать в качестве условного выражения в цикле или инструкции if.Рассмотрим, например, предыдущую программу, переписанную в более эффективном виде(результат ее выполнения аналогичен предыдущему).// Способ обойти деление на нуль с помощью ?-оператора.100100100100100100100100100100using System;class NoZeroDiv2 {public static void Main() {int i;}}for(i = -5; i < 6; i++)if(i != 0 ? true : false)Console.WriteLine("100 / " + i +" равно " + 100 / i);Обратите внимание на инструкцию if. Если значение переменной i равно нулю,результат проверки if-условия будет равен значению false, которое не допуститвыполнения инструкции вывода, а значит, и деления на нуль.
В противном случае деление(с выводом результата) будет иметь место.100Часть I. Язык C#Использование пробелов и круглых скобокЛюбое выражение в C# для повышения читабельности может включать пробелы (илисимволы табуляции). Например, следующие два выражения совершенно одинаковы, новторое прочитать гораздо легче:х=10/y*(127/x);x = 10 / y * (127/x);Круглые скобки (так же, как в алгебре) повышают приоритет операций,содержащихся внутри них. Использование избыточных или дополнительных круглыхскобок не приведет к ошибке или замедлению вычисления выражения.
Другими словами, отних не будет никакого вреда, но зато сколько пользы! Ведь они помогут прояснить (для вассамих в первую очередь, не говоря уже о тех, кому придется разбираться в этом без вас)точный порядок вычислений. Скажите, например, какое из следующих двух выраженийлегче понять?x = y/3-34*temp+127;X = (y/3) - (34*temp) + 127;Приоритет операторовВ табл. 4.2 показан порядок выполнения C#-операторов (от высшего до самогонизкого).
Эта таблица включает несколько операторов, которые описаны далее.Таблица 4.2. Приоритет C#-операторовНаивысший( ) [ ] . ++(постфиксный)--(постфиксный) checked new sizeof typeof unchecked! ~ Операторы приведения типа +(унарный) -(унарный) ++(префиксный) --(префиксный)* / %+ << >>< <= > >= is== !=&^|&&||?:= op=НизшийГлава 4. Операторы101Полныйсправочник поГлава 5Инструкции управленияВэтой главе рассматриваются инструкции управления ходом выполнения C#программы.
Существует три категории управляющих инструкций: инструкциивыбора (if, switch), итерационные инструкции (состоящие из for-, while-, do-whileи foreach-циклов) и инструкции перехода (break, continue, goto, return и throw).За исключением инструкции throw, которая является частью C#-механизма обработкиисключительных ситуаций (и рассматривается в главе 13), все остальные перечисленныевыше инструкции описаны в этой главе.Инструкция ifИнструкция if была представлена в главе 2, но здесь мы рассмотрим ее болеедетально. Полный формат ее записи такой:if(условие) инструкция;else инструкция;Здесь под элементом инструкция понимается одна инструкция языка C#. Частьelse необязательна.
Вместо элемента инструкция может быть использован блокинструкций. В этом случае формат записи if-инструкции принимает такой вид:if(условие) {последовательность инструкций}else{последовательность инструкций}Если элемент условие, который представляет собой условное выражение, привычислении даст значение ИСТИНА, будет выполнена if-инструкция; в противном случае— else-инструкция (если таковая существует). Обе инструкции никогда не выполняются.Условное выражение, управляющее выполнением if-инструкции, должно иметь тип bool.Рассмотрим простую программу, в которой используется if-else-инструкция дляопределения того, является число положительным или отрицательным.// Программа определяет, является число положительным// или отрицательным.using System;class PosNeg {public static void Main() {int i;for(i=-5; i <= 5; i++) {Console.Write("Тестирование " + i + ": ");if(i < 0) Console.WriteLine("Число отрицательно");else Console.WriteLine("Число положительно");}}}Глава 5.
Инструкции управления103Результаты выполнения программы выглядят так:Тестирование -5: Число отрицательноТестирование -4: Число отрицательноТестирование -3: Число отрицательноТестирование -2: Число отрицательноТестирование -1: Число отрицательноТестирование 0: Число положительноТестирование 1: Число положительноТестирование 2: Число положительноТестирование 3: Число положительноТестирование 4: Число положительноТестирование 5: Число положительноЕсли оказывается, что в этом примере значение переменной i меньше нуля,выполняется if-инструкция (выводится “диагноз”: Число отрицательно); в противномслучае — else-инструкция (выводится “диагноз”: Число положительно).
Обеинструкции вместе ни при каких условиях выполнены не будут.Вложенные if-инструкцииВложенные if-инструкции образуются в том случае, если в качестве элементаинструкция (см. полный формат записи) используется другая if-инструкция. Вложенныеif-инструкции очень популярны в программировании.
Главное здесь — помнить, чтоelse-инструкция всегда относится к ближайшей if-инструкции, которая находится внутритого же программного блока, но еще не связана ни с какой другой else-инструкцией. Вотпример:if(i == 10) {if(j < 20) a = b;if(k > 100) c = d;else a = c; // Эта else-инструкция// относится к if(k > 100).}else a = d; // Эта else-инструкция относится к if(i == 10).Как утверждается в комментариях, последняя else-инструкция не связана синструкцией if(j < 20), поскольку они не находятся в одном блоке (несмотря на то чтоэта if-инструкция — ближайшая, которая не имеет при себе “else-пары”).
Внутренняяelse-инструкция связана с инструкцией if(k > 100), поскольку она — ближайшая инаходится внутри того же блока.В предыдущей программе нулевое значение тестируемой переменнойинтерпретировалось как положительное. Однако в некоторых приложениях нульрассматривается как значение без знака. Поэтому в следующей версии программы, котораядемонстрирует использование вложенных else-инструкций, нулю дается именно такаяхарактеристика: “без знака”.// Программа определяет, является число положительным,// отрицательным или нулем.using System;class PosNegZero {public static void Main() {int i;for(i=-5; i <= 5; i++) {104Часть I. Язык C#}}Console.Write("Тестирование " + i + ": ");if(i < 0) Console.WriteLine("Число отрицательно");else if(i == 0) Console.WriteLine("Число без знака");else Console.WriteLine("Число положительно");}Вот какие получаем результаты:Тестирование -5: Число отрицательноТестирование -4: Число отрицательноТестирование -3: Число отрицательноТестирование -2: Число отрицательноТестирование -1: Число отрицательноТестирование 0: Число без знакаТестирование 1: Число положительноТестирование 2: Число положительноТестирование 3: Число положительноТестирование 4: Число положительноТестирование 5: Число положительноКонструкция if-else-ifОчень распространенной в программировании конструкцией, в основе которой лежитвложенная if-инструкция, является “лестница” if-else-if.