- •Лекция 4 Операции и выражения
- •Понятие выражения и операции
- •Классификация операций
- •Приоритеты (ранги) операций
- •Арифметические операции
- •Примеры использования арифметических операций Выделение цифр в целом числе
- •Выделение цифр в вещественном числе
- •Арифметические операции над переменными символьного типа
- •Операции инкремента и декремента
- •Особенности выполнения операций инкремента и декремента
- •Операции присваивания
- •Примеры использования
- •Операции отношения
- •Логические операции
- •Особенности выполнения логических операций
- •Примеры использования логических операций
- •Логические выражения и примеры их записи
- •Поразрядные логические операции
- •Примеры выполнения поразрядных логических операций:
- •Операции поразрядного сдвига
- •Дополнительные операции Операции доступа к компонентам структурированного объекта
- •Операции доступа к адресуемым компонентам классов
- •Определение размера sizeof
- •Вызов функции ( )
- •Индексация [ ]
- •Операция запятая ,
- •Операция расширения области видимости ::
- •Преобразование типа
- •Правила преобразования типов
- •Примеры преобразования типов
- •2. Особенности преобразования типов int и double:
- •7. Проанализируйте преобразование типов в операторах присваивания:
- •8. Приведение типа в случае использования указателей:
- •9. Преобразование старшего типа к младшему удобно использовать для выделения отдельных частей переменной или константы:
- •10. С помощью приведения типа можно получить дробную часть числа:
- •Программирование вычисления алгебраических выражений
- •Определение первого символа вводимого значения
- •Контроль правильности ввода значения переменной
- •Основные встроенные (стандартные) функции
- •Пример вычисления по формуле
- •Замечания по программированию алгебраических выражений
- •Особенности представления чисел по двоичному основанию*
- •Особенности выполнения арифметических операций над вещественными числами*
- •Операции умножения и деления
- •Операции сложения и вычитания
- •Особые ситуации Ошибки округления
- •Ошибки переполнения
- •Потеря (исчезновение) порядка
- •Катастрофическая потеря порядка
- •Потеря значащих цифр
- •Особенности выполнения операций отношения (сравнения)
- •Обратить внимание
- •Правила работы с данными вещественных типов
Особенности выполнения операций инкремента и декремента
Обе формы (префиксная и постфиксная) операторов возвращают значение того же типа, что и операнд. Но важное различие заключается в том, что значение, возвращаемое префиксной формой, является l-value (т.е. можно считать, что префиксная форма возвращает ссылку на операнд, имеющий уже измененное значение), в то время как значение, возвращаемое постфиксной формой оператора, не является l-value. Постфиксная форма возвращает просто значение операнда (причем не измененное, так как изменение будет произведено позже).
В этом контексте, будет возможно, но некорректно, выражение ++х = fun(x); !!! (префиксный ++ слева возвращает lvalue; x изменит свое значение, которое и будет передано в функцию, хотя лучше так не делать). При компиляции выражения x++ = fun(x); получим сообщение: error C2106: '=' : left operand must be l-value, а при компиляции выражения cout << ++x++<< endl; – сообщение: error C2105: '++' needs l-value.
//вариант 1
int fun(int);
#include <iostream>
#include <conio.h>
using namespace std;
int main() {
int x=2;
++x = fun(x); //вызывает функцию с значением 3
cout << x << endl; //3
_getch();
return 0;
}
int fun(int x)
{cout << x << endl;
return x++; //возвращает значение 3!!!
}
//вариант 2
int fun(int);
#include <iostream>
#include <conio.h>
using namespace std;
int main() {
int x=2;
++x = fun(x); //вызывает функцию с значением 3
cout << x << endl; //4
_getch();
return 0;
}
int fun(int x)
{cout << x << endl;
return ++x; //возвращает значение 4!!!
}
//вариант 3
int fun(int);
#include <iostream>
#include <conio.h>
using namespace std;
int main() {
int x=2;
x++ = fun(x); //error C2106: '=' : left operand must be l-value
cout << x << endl;
_getch();
return 0;
}
int fun(int x)
{cout << x << endl;
return ++x;
}
Что напечатает программа:
#define PRINT(int) printf (“%d\n”, int) x=y=1;
z = x++ - 1; PRINT(x ); PRINT(z); |
z=0; x=2 |
z += -x++ + ++y; PRINT(x ); PRINT(z); |
z= 0+(-2)+ 2=0; x=3; y=2; |
z = x/ ++x; PRINT(z); |
результат неопределенный из-за неопределенного порядка операций |
Операции присваивания
Оператор присваивания имеет вид:
Имя_переменной = выражение;
– значение выражения из правой части (rvalue) записывается в память по адресу, на который ссылается переменная в левой части (lvalue). При этом операция вырабатывает значение, равное значению, присвоенному переменной, находящейся в левой части операции. Это делает возможным использование операции присваивания в правой части выражений.
Слева от знака операции присваивания может быть только модифицируемое леводопустимое значение (в случае именованной типизированной константы, например, леводопустимое значение не является модифицируемым и ссылается на неизменный участок памяти).
int main()
{
int i=0; double x=0.;
x =(i = 5.25) + 6.5;
cout << i << " " << x << endl; // 5 11.5 (5+6.5)
int j=0; int ix=0;
ix=(j=5.25)+6.5;
cout << j << " " << ix << endl; // 5 11 (5+6.5)
_getch();
return 0;
}
Для более компактной записи присваивания разрешается использовать сокращенные операции присваивания ((составные присваивания: += -= *= /= %= >>= <<= &= ^= |= ). В общем виде оператор присваивания:
переменная = переменная операция выражение;
можно записать компактнее: переменная операция= выражение; (между операцией и символом = не должно быть пробела. Такая запись позволяет не повторять дважды имя одной и той же переменной. Для сокращенных операций присваивания некоторые компиляторы генерируют код, выполняемый быстрее.
Можно использовать и множественное присваивание:
переменная1 = переменная2 = … = переменнаяN = выражение;
a=b=c=d=0; //можно использовать!!!!
Это равносильно записи:
a=(в=(с=(d=0)))
int main()
{
int i=0; float x=0, y=0; bool b=false;
x = b = i = y = 4.567;
cout << y << " " << i << " " << b << " " << x << endl;
// 4.567 4 1 1
_getch();
return 0;
}
Но!!!
int main()
{
float x=0, y=4.5, z=3.2;
x = (y = z) = 6.5; // z=3.2 y=6.5 !!!!! x=6.5
cout << z << " " << y << " " << x << endl;
// 3.2 6.5!!!!! 6.5
_getch();
return 0;
}
операция |
содержание |
операция |
содержание |
x=y; |
|
k %=m; |
k=k % m; |
x +=y; |
x=x + y; |
k >>=m; |
k=k >> m сдвиг вправо на m битов |
x -=y; |
x=x - y; |
k <<=m; |
k=k << m сдвиг влево на m битов |
x *=y; |
x=x * y; |
k |=m; |
k=k | m побитовая операция логического сложения |
x /=y; |
x=x / y; |
k ^=m; |
k=k ^ m побитовая операция «исключающее или» |