Главная Случайная страница


Полезное:

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


Категории:

АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника






Операции





Знаки операций обеспечивают формирование и последующее вычисление выражений. Один и тот же знак операции может употребляться в различных выражениях и по-разному интерпретироваться в зависимости от контекста. Для изображения операций в большинстве случаев используются несколько символов. В стандарте языка Си++ определены следующие знаки операций:

[ ] (). -> ++ -- & * + - ~! sizeof

/ % << >> < > <= >= ==!= ^ | &&

||?: = *= /= %= += -= <<= >>= &= ^= |=

,::.* ->* new delete typeid

За исключением операций [], () и?: все знаки операций распознаются компилятором как отдельные лексемы. Язык Си++ даёт возможность расширить действия или, как говорят, перегрузить стандартные операции, т.е. распространить их действие на нестандартные для них операнды (объекты, например переменные, константы, над которыми выполняется операция). Опишем кратко стандартные возможности отдельных операций.

Унарные операции (операции над одним операндом):

& операция получения адреса операнда;

* операция обращения по адресу, т.е. раскрытия ссылки, иначе операция разыменования (доступ по адресу к значениям того объекта на который указывает операнд). Операндом должен быть адрес;

- унарный минус изменяет знак арифметического операнда (-3);

+ унарный плюс (введен для симметрии с унарным минусом) (+5);

~ поразрядное инвертирование внутреннего двоичного кода целочисленного аргумента (побитовое отрицание) ~5 равно -6, (5 в двоичном виде равна 00000000 00000101 при выполнении побитового отрицания получаем 11111111 11111010, что соответствует в дополнительном коде числу -6);

! логическое отрицание (НЕ) применяется к скалярным операндам целочисленный результат 0 (если операнд не нулевой, т.е. истинный) или 1 (если операнд нулевой, т.е. ложный). В качестве логического значения в языке Си++ используют целые числа: 0 – ложь и не нуль (!0) – истина. Отрицание любого ненулевого числа будет – 0, а отрицание нуля будет 1. Таким образом:!1 равно 0;!2 равно 0;!(-5.5) равно 0;!0 равно 1;

++ увеличение на единицу (инкремент или автоувеличение) унарная операция, операндом которой должно быть леводопустимое выражение;

++операнд – (префиксная операция) увеличение значения операнда на единицу до его использования в выражении; Пример:

int a = 3, b = 2;

b = (++a)-b; /*Результат работы b = 2, a = 4. Сначала а увеличивается на единицу, и только потом рассчитывается выражение b=а –b.*/

операнд++ - (постфиксная операция) увеличение значения операнда на единицу после его использования в выражении. Пример:

int a = 3, b = 2;

b = (a++)-b; /*Результат работы b = 1, a = 4. Сначала вычисляется выражение b = a – b, и только потом а увеличивается на единицу.*/

Операнд не может быть константой или произвольным выражением. Чаще всего операндами этой операции является переменные различных типов;

-- уменьшение на единицу (декремент или автоуменьшение) – унарная операция, операндом которой должно быть леводопустимое выражение;

--операнд – (префиксная операция) уменьшение значения операнда на единицу до его использования в выражении;

операнд-- - (постфиксная операция) уменьшение значения операнда на единицу после его использования в выражении.

Операнд не может быть константой или произвольным выражением. Чаще всего операндами этой операции является переменные различных типов;

sizeof операция вычисления размера (в байтах) объекта того типа, который имеет операнд. Разрешены два формата операции: sizeof унарное выражение и sizeof (тип).

Проиллюстрируем применение этой операции со стандартными типами:

//Программа 1.3

#include "stdafx.h"

#include <iostream>

void main(){

std::cout<<"\n sizeof(int) = "<<sizeof(int);

std::cout<<"\t sizeof(short) = "<<sizeof(short);

std::cout<<"\t sizeof(long) = "<<sizeof(long);

std::cout<<"\n sizeof(float) = "<<sizeof(float);

std::cout<<"\t sizeof(double) = "<<sizeof(double);

std::cout<<"\t sizeof(char) = "<<sizeof(char);

std::cout<<"\n sizeof('2') = "<<sizeof('2');

std::cout<<"\t sizeof(2) = "<<sizeof(2);

std::cout<<"\t sizeof(2L) = "<<sizeof(2L);

std::cout<<"\n sizeof(2U) = "<<sizeof(2U);

std::cout<<"\t sizeof(2.) = "<<sizeof(2.);

std::cout<<"\t sizeof(2.F) = "<<sizeof(2.F);

std::cout<<"\t sizeof(2.L) = "<<sizeof(2.L);

getchar();

}

Результаты выполнения программы приведены ниже. Они полностью согласуются с данными в табл. 2.1, т.е. объект типа int занимает в памяти два байта, объект типа short два байта и т.д. Количество памяти, отводимое под константу, зависит от её типа, а тип константы зависит от способа её записи в программе. Так, использованные в программе константы имеют следующие типы: ‘2’ – char, 2 – int, 2L – long, 2U – unsigned int, 2. – double, 2.F – float, 2.L – long double.

sizeof(int)=4 sizeof(short) = 2 sizeof(long)=4
sizeof(float)=4 sizeof(double)=8 sizeof(char)=1
sizeof(‘2’)=1 sizeof(2) = 4 sizeof(2L) = 4
sizeof(2U)=2 sizeof(2.) = 8 sizeof(2.F)=4
sizeof(2.L)=8    

Бинарные операции (операция над двумя операндами). Эти операции делятся на следующие группы:

· аддитивные;

· мультипликативные;

· сдвигов;

· поразрядные;

· операции отношений;

· логические;

· присваивания;

· выбор компонента структурированного объекта;

· операции с компонентами классов;

· операция «запятая»;

· скобки в качестве операций.

Аддитивные операции:

+ бинарный плюс (сложение арифметических операндов или сложение указателя с целочисленным операндом);

- бинарный минус (вычитание арифметических операндов или указателей).

Мультипликативные операции:

* умножение операндов арифметического типа;

/ деление операндов арифметического типа. При целочисленных операндах (константах и переменных целого типа) абсолютное значение результата округляется до целого. Например, 19/3 равно 6, -19/6 равняется - 6.

% получение остатка от деления целочисленных операндов (деление по модулю). При неотрицательных операндах остаток положительный. В противном случае остаток определяется реализацией компилятора. В компиляторе ВС++: 17%4 равняется 1, (-17)%4 равняется –1, 17%(-4) равно +1, (-17)%(-4) равняется –1. При ненулевом делителе для целочисленных операндов всегда выполняется соотношение: (a/b)*b+a%b = a.

Операции сдвига (определены только для целочисленных операндов).

Формат выражения с операцией сдвига:

левый_операнд операция_сдвига правый_операнд

<< сдвиг влево битового представления значения левого целочисленного операнда на количество разрядов, равное значению правого целочисленного операнда. Сдвиг влево на n позиций битового представления значения левого целочисленного операнда эквивалентен умножению его значения на 2n. Пример: 6<<2 равно 24 (6 в двоичной системе это 110 сдвинув влево на два разряда, т.е. дописав справа два нуля, получим в двоичной системе 11000 или 24 в десятичной);

>> сдвиг вправо битового представления значения левого целочисленного операнда на количество разрядов, равное значению правого целочисленного операнда. Сдвиг вправо на n позиций битового представления значения левого целочисленного операнда эквивалентен уменьшению его значения в 2n раз с отбрасыванием дробной части результата. Пример: 9>>2 равно 2 (9 в двоичной системе это 1001 сдвинув вправо на два разряда, т.е. отбросив справа две цифры, получим в двоичной системе 10 или 2 в десятичной).

Поразрядные операции (определены только для целочисленных операндов):

& поразрядная конъюнкция (И) битовых представлений значений целочисленных операндов;

| поразрядная дизъюнкция (ИЛИ) битовых представлений значений целочисленных операндов;

^ поразрядное исключающее (ИЛИ) битовых представлений значений целочисленных операндов.

Таблица 2.5

Таблица истинности для операций &, |, ^

a b a&b a|b a^b
         
         
         
         

 

Таблицей истинности следует пользоваться следующим образом, если а = 0 и b = 0, то результаты операций a&b, a|b, a^b в соответствии с таблицей истинности равны a&b = 0, a|b = 0, a^b = 0. Поскольку рассматриваются битовые операции, то под a и b следует понимать биты одной и той же разрядности в операндах рассматриваемых операций. Так, например:

побитовое выполнение операций &, |, ^ над операндами 9 и 7.

 

Операции отношения (сравнения):

< меньше, чем; например: 5<6 равно истина (1), 5<4 равно ложь (0);

> больше, чем; например: 5>6 равно ложь (0), 5>4 равно истина (1);

<= меньше или равно; например: 5<=5 равно истина (1), 5<=4 равно ложь (0);

>= больше или равно;

== равно;

!= не равно.

Операнды в операциях отношения арифметического типа или указатели. Результат вычисления операций отношения всегда либо 0 (ложь), либо 1 (истина).

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

&& конъюнкция (И) арифметических операндов или отношений. Целочисленный результат 0 (ложь) или 1 (истина);

|| дизъюнкция (ИЛИ) арифметических операндов или отношений. Целочисленный результат 0 (ложь) или 1 (истина).

Таблица 2.6

Таблица истинности для операций && и ||

a b a&&b a||b
       
       
       
       

 

Таблицей истинности следует пользоваться следующим образом, если а = 0 и b = 0, то результаты операций a&&b, a||b в соответствии с таблицей истинности равны a&&b = 0, a||b = 0. Поскольку рассматриваются логические операции, то под a и b следует понимать весь операнд в целом, а не отдельные его биты, причём если операнд является любым число отличным от нуля, то он истина, т.е. 1, если операнд равен нулю, то он ложь, т.е. 0. Результат логической операции всегда либо нуль (ложь), либо единица (истина). Так, например: 9&&7 = 1, 9||7 = 1, 9&&-7=1, 0&&7 = 0.

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

В качестве левого операнда присваивания может выступать только модифицированное l-значение – ссылка на некоторую именованную область памяти, значение которой доступно изменениям. Название леводопустимое выражение или l-значение произошло от изображения операции присваивания (А=Е, А стоит слева от операции присваивания), так как только l-значение может быть использовано в качестве его левого операнда. Леводоступное выражение определяет в общем случае именованную ссылку на некоторый объект, значение которого доступно изменениям. Частным случаем такой ссылки является имя переменной. Пример:

float a;

const double pi = 3.1415;

а = 2; /* переменная а – леводоступное выражение (переменной а можно присвоить значение и компилятор не выдаёт ошибки)*/

2 = а; /*неименованная константа не может быть леводоступным выражением (компилятор выдаст ошибку)*/

pi = 3.14159; /*именованная константа не может быть леводоступным выражением (компилятор выдаст ошибку) */

(а+а) = 3; /*неименованное выражение не может быть леводоступным выражением (компилятор выдаст ошибку) */

Итак, перечислим операции присваивания:

= присваивание значения выражения- операнда из правой части операнду левой части: Р= 10.3 +2*в;

*= присвоить операнду левой части произведение значений обоих операндов: Р*=2 эквивалентно Р=Р*2;

/= присвоить операнду левой части частное от деления значений левого операнда на значение правого: Р/=2.4-с эквивалентно Р=Р/(2.4-с);

%= присвоить операнду левой части остаток от деления целочисленного значения левого операнда на целочисленное значение правого операнда: Р%=В-2*С эквивалентно Р=Р%(В-2*С);

+= присвоить операнду левой части сумму значений обоих операндов: А+=А-В эквивалентно А= А+А-В;

-= присвоить операнду левой части разность значения левого и правого операндов: Х-=5.2-С эквивалентно Х=Х-5.2-С;

<<= присвоить целочисленному операнду левой части значение, полученное сдвигом влево его битового представления на количество разрядов, равное значению правого целочисленного операнда: а<<=4 эквивалентно а=a<<4;

>>= присвоить целочисленному операнду левой части значение, полученное сдвигом вправо его битового представления на количество разрядов, равное значению правого целочисленного операнда: а>>=4 эквивалентно а=a>>4;

&= присвоить целочисленному операнду левой части значение, полученное поразрядной конъюнкцией (И) его битового представления с битовым представлением целочисленного операнда правой части е&=34 эквивалентно е=е&34;

|= присвоить целочисленному операнду левой части значение, полученное поразрядной дизъюнкцией (ИЛИ) его битового представления с битовым представлением целочисленного операнда правой части а|= в эквивалентно а=а|в;

^= присвоить целочисленному операнду левой части значение, полученное применением поразрядной операции исключающего (ИЛИ) к битовым представлениям значений обоих операндов а^=х+в эквивалентно а=а^(х+в).

Обратите внимание, что для всех операций сокращенная форма присваивания Операнд1 op= Выражение эквивалентна Операнд1 = Операнд1 op (Выражение), где op – обозначение операции, т.е. всегда вычисляется сначала значение выражения и только потом выполняется операция op=.

Существует ли какая-нибудь разница при выполнении строк программы, отличающихся друг от друга только способом записи, например, (a= a+1;) или (a+=1;)? Да, разница существует и заключается только в том, что вторая строка выполняется быстрее. Последовательность действий при выполнении первой строки программы можно описать так: создаётся неименованная переменная, которая инициализируется значением переменной a; неименованная переменная увеличивается на единицу; переменной а присваивается значение неименованной переменной. Последовательность действий при выполнении второй строки программы можно описать так: переменная а увеличивается на единицу. То есть, можно сказать, что вторая строка программы выполняется приблизительно в три раза быстрее.

Операция выбора компонента структурированного объекта:

. (операция точка) прямой выбор компонента структурированного объекта, например структуры Формат применения операции:

имя_структурированного_объекта.имя_компонента;

-> косвенный выбор компонента структурированного объекта, адресуемого указателем. При использовании операции требуется, чтобы с объектом был связан указатель. В этом случае формат применения операции имеет вид:

указатель_на_структурированный_объект-> имя_компонента;

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

Операции с компонентами классов:

.* прямое обращение к компоненту класса по имени объекта и указателю на компонент;

->* косвенное обращение к компоненту класса через указатель на объект и указатель на компонент.

Комментарии по этим операциям будут даны позже после введения понятия класса.

:: операция указания области видимости имеет две формы: бинарную и унарную. Бинарная форма применяется для доступа к компоненту класса. Унарная операция:: позволяет получить доступ к внешней для некоторой функции именованной области памяти.

Запятая в качестве операции:

, несколько выражений, разделенных запятыми, вычисляются слева направо. В качестве результата сохраняются тип и значение самого правого выражения. Таким образом, операция «запятая» группирует вычисления слева направо. Тип и значение результата определяется самым правым из разделенных запятыми выражений. Значения всех левых выражений игнорируются. Например, в выражении (d = 4, f=5, d*2-f;) действия выполняются в таком порядке: переменной d присваивается 4; переменной f присваивается 5; результатом всего выражения в скобках является значение d*2-f т.е. 3.

Круглые () и квадратные [ ] скобки играют роль бинарных операций при вызове функций и индексировании элементов массивов. Таким образом, вызов функции, который имеет формат

имя_функции (список фактических параметров);

- это операция. Обращение к элементу массива, например, ar[1] - это тоже операция, которую можно записать и в таком виде ar+1.

Условная операция

В отличие от унарных и бинарных операций условная операция используется с тремя операндами. В изображении условной операции два размещённых не подряд символа?: и три операнда выражения:

выражение_1? выражение_2: выражение_3

Первым вычисляется значение выражения_1. Если оно истинно, т.е. не равно нулю, то вычисляется значение выражения_2, которое становится результатом выполнения условной операции. Если при вычислении выражение_1 получится 0, то в качестве результата берётся значение выражения_3. Классический пример:

x<0? –x: x;

Выражение возвращает абсолютное значение переменной х.

Операция явного преобразования (приведения) типа в языке Си++ имеет две различные формы. Каноническая форма, унаследованная от языка Си, имеет следующий формат:

(имя_типа) операнд

и позволяет преобразовывать значение операнда к нужному типу. В качестве операнда может быть использована переменная, константа или любое выражение, заключённое в круглые скобки.

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

имя_типа (операнд)

Она может использоваться только в тех случаях, когда тип имеет простое (несоставное) наименование. Например:

long(2); //Всё правильно ошибок нет. Создаётся неименованная константа типа //long, которая инициализируется значением 2

unsigned long (2); // Ошибка. Имя типа составное.

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

Операции new и delete для динамического распределения памяти. Эти две унарные операции используются для динамического распределения памяти. Операция

new имя_типа;

либо

new имя_типа инициализатор;

позволяет выделить и сделать доступным свободный участок в памяти, размеры которого соответствуют типу данных, определяемому именем типа. В выделенный участок заносится значение, определяемое инициализатором. В случае успешного выполнения операция new возвращает адрес начала выделенного участка памяти. Если участок нужных размеров не может быть выделен (нет памяти), то операция new возвращает нулевое значение адреса (NULL). Возвращаемый операцией new адрес необходимо сохранить в указателе для дальнейшего доступа к полученному фрагменту памяти. Поэтому обычно операция new используется в выражении

тип* имя_ указателя = new имя_типа инициализатор;

или

тип* имя_ указателя = new имя_типа;

где имя_указателя – это идентификатор.

Для явного освобождения выделенного операцией new участка памяти используется оператор

delete имя_указателя;

где имя_указателя адресует освобождаемый участок памяти, ранее выделенный с помощью операции new. Повторное применение операции delete к тому же указателю даёт неопределенный результат. Также непредсказуем результат применения этой операции к указателю, получившему значение без использования операции new. Однако применение delete к указателю с нулевым значением (NULL) не запрещено, хотя и не имеет особого смысла.

 

Таблица 2.7

Ранг операций. Ниже приведена таблица рангов (приоритетов) операций.

Ранг Операции Ассоциатив- ность
  () [] ->::. ®
  ! ~ + - ++ -- & * sizeof (унарные операции) new delete (тип) тип()  
  .* ->* ®
  * / % (мультипликативные бинарные операции) ®
  + - (аддитивные бинарные операции) ®
  << >> ®
  < <= >= > ®
  ==!= ®
  & ®
  ^ ®
  | ®
  && ®
  || ®
  ?: (условная операция)  
  = *= /= %= += -= &= ^= |= <<= >>=  
  , (операция запятая) ®

 

При вычислении выражений операции выполняются последовательно друг за другом в строгом соответствии с их рангом. В первую очередь в выражении выполняются операции с наивысшим 1-м рангом, потом 2-м рангом и т.д.. Последними выполняются операции с наинизшим 16-м рангом. Если в выражении имеются операции одного ранга, то они выполняются последовательно друг за другом в соответствии с направлением ассоциативности для этого ранга (слева направо ® или справа налево). Например, в выражении (13-4>5 && 3+5<4 && 4+5>3) восемь операций. Наивысшим ранг в данном случае пятый у аддитивных операций (-, +). Ассоциативность для этого ранга направлена слева направо поэтому операции будут выполнены друг за другом в следующем порядке (13-4), (3+5), (4+5). Найдем результат этого выражения, выполняя последовательно операции в соответствии с их рангом и ассоциативностью:

(13-4>5 && 3+5<4 && 4+5>3)

(9>5 && 3+5<4 && 4+5>3)

(9>5 && 8<4 && 4+5>3)

(9>5 && 8<4 && 9>3)

(1 && 8<4 && 9>3)

(1 && 0 && 9>3)

(1 && 0 && 1)

(0 && 1)

Таким образом, правильно используя таблицу рангов операций можно найти значение выражения любой сложности.

 

Date: 2015-05-22; view: 693; Нарушение авторских прав; Помощь в написании работы --> СЮДА...



mydocx.ru - 2015-2024 year. (0.006 sec.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав - Пожаловаться на публикацию