Операторы и выражения. Операции, приоритеты операций

Понятия оператора и выражения. Оператор — это символ, указывающий операцию, выполняемую над одним или несколькими аргументами. При выполнении оператора получается результат. Синтаксис применения операторов несколько отличен от вызова методов. Как и в большинстве других языков, семантика операторов в С# соответствует правилам и нотациям, знакомым нам со школьной скамьи. Базовые операторы в С# включают умножение (*), деление (/), сложение и унарный плюс (+), вычитание и унарный минус (—), модуль (%) и присваивание (=).

Операторы служат для того, чтобы получить новое значение из значений, над которыми производится операция. Эти исходные значения называются операндами.Результат операции должен быть сохранен в памяти. Иногда он сохраняется в переменной, содержащей один из исходных операндов. Компилятор С# генерирует сообщение об ошибке, если при использовании оператора не определяется или не сохраняется новое значение. Приведенный ниже код значений не меняет. Компилятор выдаст сообщение об ошибке, так как арифметическое выражение, не приводящее к изменению хоть одного значения, обычно рассматривается как ошибочное.

class NoResultApp
{
public static void Main()
{
int i; int j;
i + j; // Ошибка, поскольку результат ничему не присваивается.

}

}

Арифметические операции.С#, как и большинство других языков, поддерживает основные математические операции: умножение (*), деление (/), сложение (+), вычитание (—) и остаток от деления одного целого числа на другое (%). Операция (div – целочисленное деление) в современных языках программирования отсутствует! Если целое число делится на целое, то результат операции «/» – целая часть частного. Если хотя бы один из операндов имеет вещественный тип, то результат операции – вещественное число.

Примеры:

15/2=7;

15/2.0=7.5.

Комбинированные операторы присваивания. При вычислении выражений можно использовать комбинированные операторы присваивания:

+= сложить два операнда и результат присвоить левому операнду.

-= вычесть два операнда и результат присвоить левому операнду.

*=умножить два операнда и результат присвоить левому операнду.

/= разделить два операнда и результат присвоить левому операнду.

Пример:

int i = 10; или int i = 10,a=3;

int a=3;

Выполним операцию i += a; В результате получим i = 13, a=3.

Компилятор не переводит выражение наподобие х += 5 в х = х + 5, он действует логически.

На языке Pascal аналогичная операция записывается следующим образом: i :=i+a.

Логические операции:

· И (конъюнкция) – обозначается символами &&;

· ИЛИ (дизъюнкция) – обозначается символами ||;

· НЕ (отрицание) – обозначается символом !.

Операции отношения или сравнения (<, >, <=, >=, ==, !=). Большинство операций возвращает числовые значения. Что касается операций отношения, они генерируют булевский результат. Вместо того чтобы выполнять математические операции с набором операндов, операции отношения анализируют соотношение между операндами и возвращаютзначение true,если соотношение истинно, false — если ложно.

К операторам отношения, называемым операторами сравнения,относятся«меньше» (<), «меньше или равно» (<=), «больше» (>), «больше или равно» (>=), «равно» (==) и «не равно» (!=). Применение этих операторов к числам понятно, но при использовании с объектами их выполнение не так очевидно.

Операторы инкрементирования (++) и декрементирования (--). Операторы ++, -- увеличивают, уменьшают числовую переменную целого или вещественного типа на единицу. Существует две разновидности каждого из этих операторов:

· В префиксном варианте ++x: изменение значения переменной x выполняется до обработки операнда. Говорят: «Сначала увеличь переменную х на единицу, а затем используй новое значение при вычислении выражения».

Пример:

int x = 5;

int y = ++x;

Результат: y=6, х=6

· В постфиксном варианте x++:изменение значения переменной x выполняется после обработки операнда. Говорят: «Используй текущее значение переменной х при вычислении выражения, а затем увеличь её на единицу».

Пример:

int z = 5;

int y = z++;

Результат: y=5, z =6

Большинство операторов работает только с числовыми типами данных, такими как byte, short, long, int, single, double и decimal.Исключение — операторы сравнения (== и !=). Кроме того, в С# можно применять операторы + и — для класса Stringи даже применять операторы инкремента (++) и (—) для таких необычных языковых конструкций как делегаты.

Приоритет (старшинство) операторов.Когда в одном выражении несколько операторов, компилятор должен определить порядок их выполнения. При этом компилятор руководствуется правилами, которые называются старшинством операторов. Понимание приоритетаоператоров нужно для правильного написания выражений — иногда результат может не соответствовать ожидаемому.

Рассмотрим выражение 42 + 6 * 10. Если сложить 42 и 6, а затем сумму умножить на 10, получится 480. Если же умножить 6 на 10 и к результату прибавить 42, получится 102. При компиляции кода специальный компонент компилятора — лексический анализатор — отвечает за порядок чтения этого кода. Именно лексический анализатор определяет относительное старшинство разнородных операторов в одном выражении. Для этого он использует некоторое значение — приоритет — каждого поддерживаемого оператора. Более приоритетные операторы разрешаются в первую очередь. В нашем примере оператор * имеет старшинство над оператором +, так как * поглощаетсвои операнды до того, как это сделает +. Объяснение кроется в общих арифметических правилах: умножение и деление всегда имеют более высокий приоритет,чем сложение и вычитание. Вернемся к примеру: говорят, что число 6 поглощенооператором * и в 42 + 6 * 10 и в 42 * 6 + 10, так что эти выражения эквивалентны 42 + (6 * 10) и (42 * 6) + 10.

Теперь посмотрим, как старшинство операторов определяется в С#. Ниже операторы перечислены в порядке убывания приоритета (табл. 1). Рассмотрим различные категории операторов, поддерживаемых в С#.

Табл. 1. Старшинство операторов в С#

Категория оператора Операторы
Простой (х), х.у, f(x), а[х], х++, х — , new, typeof, sizeof, checked, unchecked
Унарный + , -, !, ++x, — х, (Т)х
Мультипликативный *, /, %
Аддитивный +, -
Сдвиг «, »
Отношение <, >, <=, >=, is
Равенство ==
Логическое И (AND) &
Логическое исключающее ИЛИ (XOR) ^
Логическое ИЛИ (OR) I
Условное И (AND) &&
Условное ИЛ И (OR) II
Условие ()
Присваивание = *= /= % = , + = , -= « = , » = , &=, ^ = , =

Левая и правая ассоциативность. Ассоциативность определяет, какая часть выражения должна быть вычислена первой. Например, результатом выражения 42—15–6 может быть 21 или 33 в зависимости от того, какая ассоциативность будет применяться для оператора «—»: левая или правая.

Оператор — имеет левую ассоциативность, т. е. сначала вычисляется 42—15, а затем из результата вычитается 6. Если бы он имел правую ассоциативность, сначала вычислялась бы правая часть выражения (15—6), а затем результат вычитался бы из 42.

Все бинарные операторы (операторы с двумя операндами), кроме операторов присваивания, — лево-ассоциативные, т. е. они обрабатывают выражения слева направо. Таким образом, а +b + с — то же, что и (а +b) + с, где сначала вычисляется а +b, а затем к сумме прибавляется с.

Операторы присваивания и условные операторы — право-ассоциативные, т. е. обрабатывают выражения справа налево. Иначе говоря, а=b=сэквивалентно а = (b = с).Многие на этом спотыкаются, когда хотят поместить в одну строку несколько операторов присваивания, так что давайте рассмотрим такой код:

using System;
class RightAssocApp

{
public static void Main()

{
int a = 1; int b = 2; int с = 3;
Console.WriteLine("a={0} b={1} c={2>", a, b, c);

a = b = c;
Console.WriteLine("После "a=b=c - : a={0} b={1} c={2}", a, b, c);

}

}

Результат выполнения этого примера таков:

а=1 b=2 с=3

После 'а=b=с': а=3 b=3 c=3

Поначалу вычисление выражений справа налево может сбивать с толку, но давайте подойдем к этому так: если бы оператор присваивания был лево-ассоциативным, компилятор сначала должен был бы вычислить а = b,после чего абыло бы равно 2, а затем b= с и в результате bбыло бы равно 3. Конечный результат был бы а=2 b=3 с=3.Очевидно, что мы ожидаем не этого, когда пишем а = b = с, и именно поэтому операторы присваивания и условные операторы право-ассоциативные.

3.2. Преобразование типов в выражениях

Простые операторы присваивания. Значение в левой части оператора присваивания называется lvalue,а в правой части — rvalue. В качестве rvalueможет быть любая константа, переменная, число или выражение, результат которого совместим с lvalue. Между тем lvalue должно быть переменной определенного типа. Дело в том, что значение копируется из правой части в левую. Таким образом, для нового значения должно быть выделено физическое адресное пространство. Например, можно написать а= 4,поскольку для а есть место в памяти — в стеке или в куче — в зависимости от типа переменной. А вот оператор 4 = авыполнить нельзя, так как 4 — это значение, а не переменная, содержимое которой в памяти можно изменить. В С# в качестве lvalueможет быть переменная, свойство или индексатор.

Если с присваиванием числовых значений все достаточно понятно, с объектами дело сложнее. Напомним, что когда вы имеете дело с объектами, вы манипулируете не элементами стека, которые легко копировать и перемещать. В случае объектов у вас на самом деле есть лишь ссылки на некоторые сущности, для которых динамически выделена память. Следовательно, когда вы пытаетесь присвоить переменной объект (или любой ссылочный тип) копируются не данные, как это происходит в случае размерных типов, а ссылки. Скажем, у вас два объекта: testl и test2.Если вы укажете testl = test2, testlне будет копией test2.Они будут совпадать! Объект testlуказывает на ту же память, что и test2,и любые изменения объекта testlприведут к изменениям test2.

11. Одномерные массивы. Способы создания элементов массива.(2 лаб)

В отличие от другихязыков программирования массивы в С# реализованы как объекты. Тип массив определён в системном типе System.Array. Массив – это набор элементов данных одного типа, сохранённых в непрерывной области памяти. Массив в С# содержит список ссылок на ячейки памяти, в которых сохранены элементы массива. Массив может быть объявлен с указанием любого типа данных.

Типы массивов.В зависимости от числа измерений массивы делятся на:

– одномерные;

– многомерные (самый простой из них – двумерный);

– ступенчатые (ломаные, изрезанные).

В С# размер массива не нужно указывать при его объявлении. Этим достигается большая гибкость, так как размер определяется в тот момент, когда массив будет использоваться.

Объявление одномерного массива:

Тип_элементов [ ] Имя_массива = new Тип_элементов [размер];

Так как массивы определяются как объекты, их создание представляет собой двухступенчатый процесс. Сначала объявляется ссылочная переменная на массив, а затем с помощью оператора new для него выделяется память, и переменной массива присваивается ссылка (адрес)на эту область памяти.

Пример создания массива:

int [ ] mas1 = new int [5];

Операторы и выражения. Операции, приоритеты операций - student2.ru

Так как массивы представляют собой ссылки, для создания объекта массива типа int обязательно ключевое слово new. Такое объявление массива называется ранним связыванием.

Можно сначала объявить массив, а затем выделить ему память:

short [] mas2;

//… программный код

mas2=new short [n]; //n (размер) должен быть уже установлен. Такое объявление массива называется поздним связыванием.

Наши рекомендации