Файл: 25. Операторы относительные приоритеты. Побитовые операторы. Операторы присваивания. Относительные приоритеты.docx
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 09.01.2024
Просмотров: 36
Скачиваний: 1
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
25. Операторы – относительные приоритеты. Побитовые операторы. Операторы присваивания.
Относительные приоритеты:
1) унарные + и -;
2) *, /, %
3) +, -
Побитовые операторы
В Си имеются шесть операторов для манипулирования с битами. Их
можно применять только к целочисленным операндам, т. е. к char, short,
int и long, знаковым и беззнаковым:
& - побитовое И
| - побитовое ИЛИ
^ - побитовое исключающее ИЛИ
<< - сдвиг влево
>> - сдвиг вправо
- побитовое отрицание (унарный)Оператор & (побитовое И) часто используется для обнуления
некоторой группы разрядов.
Например:
n = n & 0177;
обнуляет в n все разряды, кроме младших семи.
(001 111 111)
Оператор |(побитовое ИЛИ) применяют для установки разрядов; так,
#define SET_ON 0177
х = х |SET_ON;
устанавливает единицы в тех разрядах х, которым соответствуют единицы в SET_ON.
Оператор ^(побитовое исключающее ИЛИ) в каждом разряде установит 1, если соответствующие разряды операндов имеют различные значения, и 0, когда они совпадают:
Операторы<<и >> сдвигают влево или вправо свой левый операнд на число битовых позиций, задаваемое правым операндом, который должен быть неотрицательным.
Операторы присваивания
Присваивание i = i + 2, можно написать в сжатом виде:
i += 2;
Имеются следующие операторы присваивания:
ор=, где <ор>::= + | - | * | / | %| << | >> | & | ^ | | (побит. или)
i*=2; /* i=i*2 */
x*=y+1; /* x=x*(y+1) */
Присваивание может применяться в выражениях!:
while ((с=getchar())!=EOF)
int bitcount(unsigned x) {// bitcount: подсчет единиц в х
int b;
for (b=0; x!=0; x>>=1)
if (x & 01) b++;
return b;}
int main ( ){
unsigned x=7; int n=bitcount(x);
printf("n=%d",n);
}
26. Преобразования типов данных
Преобразования типов при вычислении выражений
Если операнды оператора принадлежат к разным типам, то они
приводятся к некоторому общему типу. Обычно автоматически
производятся лишь те преобразования, которые без какой-либо потери
информации превращают операнды с меньшим диапазоном значений в
операнды с большим диапазоном (целое -> вещественное). Возможны
преобразования c потерей информации.
Например:
long int int; float int;
Однако при этом могут выдаваться предупреждения.
Значения типа char – это малые целые, и их можно использовать в
арифметических выражениях.
Преобразования типов
Заголовочный файл
функций для преобразования символов. Например:
tolower(c) дает код строчной буквы с;
isdigit(c) выполняет проверку с >= '0' && с <= ‘9‘.
Существует одна тонкость: язык не определяет, являются ли
переменные типа char знаковыми или беззнаковыми. Поэтому
преобразование char с единичным старшим битом в int на одних машинах
будет превращено в отрицательное целое (посредством "распространения
знака"). На других – преобразование char в int осуществляется
добавлением нулей слева, и, таким образом, получаемое значение всегда
положительно.
Гарантируется, что любой отображаемый символ из стандартной
кодовой таблицы никогда не будет отрицательным числом.
Поэтому переменные типа char, в которых хранятся числа, следует
специфицировать явно как signed или unsigned.
Преобразования типов
В общем случае, когда бинарный оператор имеет разнотипные
операнды, прежде чем операция начнет выполняться, "низший" тип
повышается до "высшего". Результат будет иметь высший тип.
Набор неформальных правил для преобразования типов в
выражениях, когда нет беззнаковых операндов:
1) если один из операндов принадлежит типу long double, то и другой
приводится к long double.
2) иначе, если один из операндов принадлежит типу double, то и
другой приводится к double.
3) иначе, если один из операндов принадлежит типу float, то и другой
приводится к float.
4) иначе операнды типов char и short приводятся к int.
5) и наконец, если один из операндов типа long, то и другой приводится
к long.
Преобразования типов
Правила преобразования усложняются с появлением операндов типа
unsigned.
Сравнение знаковых и беззнаковых значений зависит от размеров
целочисленных типов, которые на разных машинах могут отличаться.
Пусть int занимает 16 битов, long – 32 бита.
Тогда
1) -1L < 1U (int приводится к long)
2) -1L > 1UL (long приводится к unsigned long)
#include
using namespace std;
int main() {
cout<<5/2<
27. Приоритеты операций и порядок вычислений.
Приоритет | Операция | Ассоциативность | Описание |
1 | :: | слева направо | унарная операция разрешения области действия |
[ ] | операция индексирования | ||
() | круглые скобки | ||
. | обращение к члену структуры или класса | ||
-> | обращение к члену структуры или класса через указатель | ||
2 | ++ | слева направо | постфиксный инкремент |
— | постфиксный декремент | ||
3 | ++ | справа налево | префиксный инкремент |
— | префиксный декремент | ||
4 | * | слева направо | умножение |
/ | деление | ||
% | остаток от деления | ||
5 | + | слева направо | сложение |
— | вычитание | ||
6 | >> | слева направо | сдвиг вправо |
<< | сдвиг влево | ||
7 | < | слева направо | меньше |
<= | меньше либо равно | ||
> | больше | ||
>= | больше либо равно | ||
8 | == | слева направо | равно |
!= | не равно | ||
9 | && | слева направо | логическое И |
10 | || | слева направо | логическое ИЛИ |
11 | ?: | справа налево | условная операция (тернарная операция) |
12 | = | справа налево | присваивание |
*= | умножение с присваиванием | ||
/= | деление с присваиванием | ||
%= | остаток от деления с присваиванием | ||
+= | сложение с присваиванием | ||
-= | вычитание с присваиванием | ||
13 | , | слева направо | запятая |
Порядок вычислений
Пример1:
int x=3, y=4,z=5;
cout<
выполнения операции: cout<
переменной y, затем значение переменной z.
Пример2:
int x, y, z;
x=y=z=5;
Операция присваивание ―=‖ выполняется справа налево, поэтому
сначала переменная z получает значение 5, затем переменной y будет
присвоено значение переменной z, и только потом переменной x будет
присвоено значение y.
Порядок вычислений
Си не фиксирует очередность вычисления операндов оператора (за
исключением && , || , ? : и , ) . Например, в инструкции вида
х = f() + g();
f может быть вычислена раньше g или наоборот.
Очередность вычисления аргументов функции также не определена,
поэтому на разных компиляторах вызов
printf("%d %d\n", ++n, power(2, n)); /* НЕВЕРНО */
может давать несовпадающие результаты. Результат вызова функции
зависит от того, когда компилятор сгенерирует команду увеличения n —
до или после обращения к power.
Правильно:
++n;
printf("%d %d\n", n, power(2, n));
Порядок вычислений
a[i]=i++;
Возникает вопрос: массив а индексируется старым или измененным
значением i?
Компиляторы могут по-разному генерировать программу, что проявится
в интерпретации данной записи.
Мораль такова: писать программы нужно так, чтобы они не
зависели от очередности вычислений
28.Базовые конструкции структурного программирования. Операторы ветвления if-else и ?:. Пример программы
Операторы ветвления if-else
Инструкция if-else используется для принятия решения. Формально
ее синтаксисом является:
if (<выражение>) <оператор1>; [else <оператор2;>]
причем else-часть может и отсутствовать.
Составной оператор – это последовательность операторов,
заключенная в фигурные скобки {}.
Примеры:
if (а<0) b = 1;
if (ad || a==0)) b++; else {b *=a; a = 0;}
if (aif (a++) b++; //условие не обязательно операция отношения
Пример: if (a++) b++; рассмотрим подробнее, при каких значениях
переменной а, переменная b изменит значение?
int main (){
int a=0, b=0;
if (a++) b++;
cout<<"a="<Пример вычисления функции, определяемой многими условиями.
#include
#include
int main() {
SetConsoleOutputCP(65001);
double x,y;
printf("введите x");
scanf("%lf",&x);
if (x<-2) y=0;
else if (x<-1) y=-x-2;
else if (x<1) y= x;
else if (x<2) y=-x+2;
else y=0;
printf("y=%g",y);
return 0;
} #include
#include
int main() {
SetConsoleOutputCP(65001);
double x,y;
printf("введите x");
scanf("%lf",&x);
if (x<-2) y=0;
else if (x<-1) y=-x-2;
else if (x<1) y= x;
else if (x<2) y=-x+2;
else y=0;
printf("y=%g",y);
return 0;
}
30. Базовые конструкции структурного программирования. Оператор ветвления switch. Пример программы.
Базовые конструкции структурного программирования
В теории программирования доказано, что программу для решения задачи любой сложности можно составить только из трех структур, называемых следованием, ветвлением и циклом. Этот результат установлен Боймом и Якопини в 1966 году путем доказательства того, что любую программу можно преобразовать в эквивалентную, состоящую только из этих структур и их комбинаций. Следование, ветвление и цикл называют базовыми конструкциями структурного программирования.
Следованием называется конструкция, представляющая собой последовательное выполнение двух или более операторов
Ветвление задает выполнение либо одного, либо другого оператора в зависимости от выполнения какого-либо условия (рис1.2).
Если условие выполняется, то а = -а, иначе а = b.
Цикл задает многократное выполнение оператора 1, пока выполняется условие
Операторы ветвления switch
Инструкция switch используется для выбора одной из нескольких ветвей
алгоритма. Формат вызова:
switch ( выражение ) {
case константное_выражение_1: [операторы_1];
case константное_выражение_2: [операторы_2];
case константное_выражение_n: [операторы_n];
[default: операторы ];
}
Пример: по номеру месяца определим время года
#include
#include
int main() {
SetConsoleOutputCP(65001);
int i;
printf("введите номер месяца");
scanf("%d",&i);
switch (i) {
case 1: case 2: case 12:printf("зима");break;
case 3: case 4: case 5: printf("весна"); break;
case 6: case 7: case 8: printf("лето"); break;
case 9: case 10: case 11:printf("осень"); break;
default: printf("error");
}
return 0;
}
Операторыветвления switch
#include
main() { /* подсчет цифр, пробелов и прочих символов */
int c, i, nwhite, nother, ndigit[10];
nwhite = nother = 0;
for (i = 0; i < 10; i++)
ndigit[i] = 0;
while ((c = getchar()) != EOF) {
switch (c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
ndigit[c - '0' ]++; break;
case ' ': case '\n': case '\t': nwhite++; break;
default: nother++;
}
}
printf ("цифр =");
for (i= 0; i < 10; i++)
printf (" %d", ndigit[i]);
printf (", пробелов= %d, прочих = %d\n", nwhite, nother);
return 0;
}
Операторы ветвления switch
Инструкция break вызывает немедленный выход из переключателя
switch. Поскольку выбор ветви case реализуется как переход на метку,
то после выполнения одной ветви case, если ничего не предпринять,
программа провалится вниз на следующую ветвь.
Инструкции break и return – наиболее распространенные средства
выхода из переключателя.