Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

C_Kurs_Lekt / C_I_семестр / 02_Операции_в_Си

.pdf
Скачиваний:
10
Добавлен:
13.02.2016
Размер:
131.89 Кб
Скачать

Лысый Д.А. Лекция(продолжение) Операции в Си

1

ОПЕРАЦИИ ЯЗЫКА СИ

Таблица приоритетов рангов операций С

 

Ðàíã

Операции

 

 

 

Ассоциативность

 

1

() [] .

 

 

 

->

 

2

! ~ + - ++ -- & * (тип) sizeof тип() (функциональное преобразо-

<-

 

 

вание типа)

 

 

 

 

 

3

* / % (мультипликативные бинарные операции)

->

 

4

+ - (аддитивные бинарные операции)

->

 

5

<<

>>

 

 

 

 

->

 

6

<

<=

>=

>

 

 

->

 

7

==

!=

 

 

 

 

->

 

8

&

 

 

 

 

 

->

 

9

^

 

 

 

 

 

->

 

10

|

 

 

 

 

 

->

 

11

&&

 

 

 

 

 

->

 

12

||

 

 

 

 

 

->

 

13

?: (условная операция)

 

<-

 

14

=

*=

/=

%= +=

-=

&= ^= |= <<= >>=

<-

 

15

, (операция запятая)

 

->

Отношения и логические операции

 

 

 

Знаки операций отношения:

 

 

 

==

равно;

 

 

!=

неравно;

 

<

меньше, чем;

<=

меньше или равно;

 

>

больше, чем;

 

>=

больше или равно.

 

Логический тип в языке Си отсутствует, поэтому принято, что отношение имеет любое ненулевое положительное значение (обычно 1), если оно истинно, и равно 0, если оно ложно. Ничто не противоречит применению логических операций к це-

лочисленным значениям.

 

 

 

 

 

Примеры:

 

 

 

 

 

5<7

равняется 1;

 

 

 

 

 

5>7

равняется 0;

 

 

 

 

 

5==7

равняется 0;

 

 

 

 

Логических операций в языке Си три. Приведем таблицы истинности этих операций.

Таблицы истинности логических операций

 

 

 

! - отрицание, т.е. логическое НЕ ;

 

 

 

 

 

Выражение

 

 

 

Результат (!Выражение)

 

 

 

0

 

 

 

1

 

 

ненулевое

 

 

 

0

 

&& -конъюнкция, т.е. логическое И;

 

 

 

 

 

выражение1

 

 

выражение2

выражение1&& выражение2

 

 

0

 

 

0

 

0

 

 

0

 

 

ненулевое

0

 

 

ненулевое

 

 

0

 

0

 

 

ненулевое

 

 

ненулевое

1

 

|| - дизъюнкция, т.е. логическое ИЛИ

 

 

 

 

 

выражение1

 

 

выражение2

выражение1 || выражение2

 

 

0

 

 

0

 

0

 

 

0

 

 

ненулевое

1

 

 

ненулевое

 

 

0

 

1

 

 

ненулевое

 

 

ненулевое

1

5!=7

равняется 1;

 

 

 

7!=5 || 7<5

равняется 1;

 

 

 

56>5 && 3*15>44 && 45+1>3

равняется 1.

 

Поразрядные операции:

~поразрядное инвертирование внутреннего двоичного кода целочисленного аргумента (побитовое отрицание)

«переворачивает» значение каждого бита на противоположное. Так, если А в двоичном виде представляется как 01101100, то ~ А станет 10010011:

~ [1] = 0 ~ [0] = 1

Квадратные скобки вокруг аргументов обозначают действие над одним битам.

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

[0]& [1] = [1] & [0] = [0]

[0]& [0] = [0]

[1]& [1] = [1]

Лысый Д.А. Лекция(продолжение) Операции в Си

2

 

Квадратные скобки вокруг аргументов обозначают действие над одним битам.

 

Пример: (6 & 4) = 4, (6 & 1) = 0. Рассмотрим 6 и 4 как двоичные числа:

 

0000110

(6)

 

 

0000110

 

&

 

0000100

(4)

и

& 0000001

(1)

 

 

0000100

(4)

 

 

0000000

(0)

Обычно операция & используется для двух целей: проверить наличие битов или убрать { т.е. обнулить) некоторые из них. Например, надо проверить состояние бита номер 5 (нумерация идет справа налево, от 0 до 7). Единица в бите 5 дает число 2 - 32. Это второй аргумент. Если в А в пятом бите есть единица, то должно выполниться усло-

âèå ( A & 32 ) = 32. Осталось оформить все это в оператор IF. Можно проверить наличие сразу нескольких «включенных» битов, например, 5-го, 2-го и 0-го. Число с единицами в этих позициях и нулями в остальных равно 2 + 2 + 1 = 32+4+1 = 37. Если А среди прочих имеет единицы в битах 5, 2 и 0, то в этом случае будет истинным выражение

( A & 37 ) = 37

Исключение или выключение битов достигается следующим образом. Пусть надо исключить бит 3 из переменной А типа Char. Исключить — значит, задать нулем. Первым делом определяется число, в котором все биты равны 1, кроме бита номер 3. Для типа Char оно равно (255 - 23 = 247, где 255 — максимальное значение вписываемое в байт. Если теперь это число логически умножить на А, то единицы в 247 никак не повлияют на состояние битов в переменной А, а ноль в третьем бите заместит любое значение в А на том же месте. Таким образом, можно записать А = A & (255 - 8); чтобы получить значение А с отключенным 3-м битом.

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

[1] | [0] = [0] | [1] = [1]

[0]| [0] = [0]

[1]| [1] = [1]

Квадратные скобки обозначают один бит. Эта операция может с успехом применяться при включении (установки в 1) отдельных битов двоичного представления целых чисел. Так, если надо, чтобы бит 4 значения А стал равным единице, а остальные не изменились, то следует записать

А = A | 16;

Аналогичным образом можно включать сразу несколько битов, например, 4-й, 1-й и 0-й:

А= A | (16 + 2 + 1);

^поразрядное исключающее ИЛИ битовых представлений целочисленных операндов; (математическое название — «сложение по модулю 2»). Эта операция возвращает 0, когда оба ее аргумента равны, и 1 в противном слу- чае:

[1] ^ [1] = [0]

[0]^ [0] = [0]

[1]^ [0] = [0] ^ [1] = [1]

Операцию ^ можно с успехом применять при смене значения бита (или нескольких битов) на противоположные. Пусть необходимо переключить состояние бита 5 числа А. Это будет сделано операцией А ^ 32 , где 32 = 25.

Исключающее 'ИЛИ' обладает одной особенностью: примененное дважды к одной и той же переменной, оно восстановит ее исходное значение, т.е. всегда выполняется равенство:

А = ( А ^ В ) ^ В

Операции сдвигов » (вправо) и « (влево) должны иметь целочисленные операнды. Над битовым представлением значения левого операнда выполняется действие - сдвиг. Правый операнд определяет величину поразрядного сдвига.

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

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

При положительном левом операнде сдвиг вправо на N позиций эквивалентен уменьшению значения левого операнда в 2N раз с отбрасыванием дробной части результата. (Поэтому 5>>2 равно 1.)

Например, число с двоичным представлением 11011011 будет трансформироваться при сдвигах влево следующим образом:

( 11011011

<< 0 ) = 11011011

( 11011011

<< 1 ) = 10110110

( 11011011

<< 2 ) = 01101100

( 11011011

<< 3

) = 11011000

( 11011011

<< 4

) = 10110000

( 11011011

<< 7

) = 10000000

( 11011011

<< 8

) = 00000000

++- увеличение на единицу (инкремент или автоувеличение) как и

--- уменьшение на единицу (декремент или автоуменьшение) ; имеет две формы:

префиксная операция - увеличение значения операнда на 1 до его использования. Ассоциативность справа в соответствии со стандартом;

постфиксная операция - увеличение значения операнда на 1 после его использования. Ассоциативность слева в

Лысый Д.А. Лекция(продолжение) Операции в Си

3

соответствии со стандартом.

Операндами унарных операций ++ и — должны быть всегда модифицируемые именующие выражения (L-value, left value, /-значение, леводопустимое выражение). Термины "леводопустимое выражение" и "l-значение" происходят от объяснения действия операции присваивания Е = D, в которой операнд Е слева от знака операции присваивания может быть только модифицируемым l-значением. Примером модифицируемого /-значения служит имя переменной, которой выделена память. Таким образом, /-значение - ссылка на область памяти, значение которой доступно изменениям;

выражение ++n увеличивает на 1 значение n, и это полученное значение используется как значение выражения ++n (префиксная форма);

выражение —k уменьшает на 1 значение k, и это новое значение используется как значение выражения --k (префиксная форма);

выражение i++ (постфиксная форма) увеличивает на 1 значение i, однако значением выражения i++ является предыдущее значение i (до его увеличения);

выражение j— (постфиксная форма) уменьшает на 1 значение j, однако значением выражения j— является предыдущее значение j (до его уменьшения).

Например, если n равно 4, то при вычислении выражения n++*2 результат равен 8, а n примет значение 5. При n, равном 4, значением выражения ++n*2 будет 10, а n станет равно 5.

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

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

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

х < 0 ? -х : х; Выражение возвращает абсолютную величину переменной х.

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

sizeof не вычисляет значения выражения, а только определяет его тип, для которого затем вычисляется размер.

Пример: для определения количества элементов в массиве A[4] можнл использовать следующее выражение - sizeof (A)/ sizeof(A[0])

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

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

#include <stdio.h> main(){

double i=10., j=20.,k; k=(i++,k=0,k=i*3)+j; printf("\n%lf",k);

}

Резóльтат k=53.0