Бинарная операция использует два операнда, а унарная – один операнд.
Большинство операций языка Си совпадают с операциями языка ассемблер.
Унарные (однооперандные) операции
1. & - операция получения адреса операнда.
2. * - операция обращения по адресу, или операция разыменования, т.е. р = *а доступна по адресу к объекту на который указывает операнд.
3. − - изменяет знак арифметического операнда, а если операнд без знаковый, то результатом операции является величина 2n, где n – число бит, выделяемое под данную переменную.
4. ~ - поразрядное инвертирование внутреннего двойного кода целочисленного аргумента, или побитовое отрицание.
5. ! – это логическое отрицание значения операнда, результатом является ноль, если операнд ненулевой и результатом является единица, если операнд нулевой.
Пример №1:
! 0 =1
! 5=1
! 100=0
! (-90)=0
6. ++ - увеличение на 1 операнда, имеет две формы:
• префиксная операция: увеличение значения операнда на 1 до его использования,
• постфиксная операция: увеличение значения операнда на 1 после его использования.
7. -- - уменьшение на 1 (декремент), также имеет две формы:
• префиксная,
• постфиксная.
Операндами для обоих операций не может быть константа и производное выражение (++5 ; ++(j+k)).
Операндами этих операций должны быть модифицируемые именные переменные
8. sizeof – операция вычисления размера в байтах для операнда. Имеет две формы:
• sizeof выражение (р.а или р+а или ...)
• sizeof тип
Бинарные (двухоперандные) операции.
1. Арифметические операции в Си
x + y – операция «сложение»
x - y – операция « вычитание»
x * y – операция « умножение»
x / y – операция « деление». Если числа целые, то результат - целое число с отброшенной дробной частью - не округленное! Т.е., если в результате деления на калькуляторе получается 6.23411 или 6.94, то результат будет просто целое число 6 - запомните!
Если числа с плавающей точкой, то есть float или double и записываются с точкой и числом после точки, то и результат будет число с плавающей точкой .
x % y – операция «вычисления остатка от деления нацело».
Примеры:
5 / 2 – дает 2
5 % 2 – дает 1
2. Операция сдвига: определены только для целочисленных операндов:
<< - операция сдвиг влево битового представления значения левого целочисленного операнда на количество разрядов, равное значению правого целочисленного операнда.
3. Поразрядная операция:
^ - операция «поразрядное сложение по модулю два» (исключающее ИЛИ) битовых представлений значений целочисленных операндов.
4. Операции отношений или сравнений.
Используются для сравнения переменных, чисел (констант) и выражений.
x < y – операция «x меньше y»
x > y – операция «больше»
x <= y – операция «меньше или равно»
x >= y – операция «больше или равно»
x == y – операция «равно»
x != y – операция «не равно».
Результат выполнения этих операций:
"истина" это "1" (точнее "не ноль")
"ложно" это "0
Значения, хранимые в переменных (в регистрах) х и у, НЕ изменяются! Берутся (считываются) значения хранящиеся (или содержащиеся) в переменных и сравниваются.
5. Логические операции:
|| - операция "ИЛИ" - только "ложь" и "ложь" дают «ложь». Дизъюнкция (ИЛИ) арифметических операндов.
Пример: у= 5||1, у=1;
у=5||0, у=1.
&& - операция «конъюнкции» (И) арифметических операндов или отношений. Результат целочисленный: О или 1."И" - только "истина" и "истина" дают "истина".
Пример №2:
р = 5&&4 => р = 1
(1) (1)
р = 5&&0 => р = 0
(1) (0)
! – операция "НЕ" - логическое отрицание
Правило - в Си считается:
"Ложь" (False) только ноль.
"Истина"(True)- не ноль или так: (!0) */
! (истина) – дает "ложь"
! (ложь) – дает "истина"
В результате логической операции вы получаете НЕ ЧИСЛО, а логическое значение "истина" или "ложь".
Для логических операций && и || берутся результаты выражений слева и справа от знака операции, преобразованные в "истину" или "ложь", и определяется логический результат операции.
Компилятор результат "истина" превращает в 1, а не в любое отличное от 0 число.
Совет: Используйте скобки:
( () + ( () * () ) ),
чтобы точно знать порядок выполнения операций программой!
Логические операции могут объединять несколько проверяемых условий.
Например:
if ((выражение1)&&((выражение2)||(выражение3)))
{
/* Код программы здесь будет выполняться если: Выражение1 "Истина" (значит не ноль) и хотя бы одно из выражений 2 и 3 тоже "Истина" (значит не ноль). */
};
6. Операция присваивания.
Чтобы поместить число в переменную (в регистр) в Си, есть оператор присваивания это знак =, называемый в математике "равно".
= в Си означает вычислить результат того, что справа от оператора присваивания и поместить этот результат в переменную находящуюся левее оператора присваивания.
PORTB = PINB + 34; Эта строчка на Си означает: взять (прочитать, считать) значение переменной (регистра) PINB, затем прибавить к нему число 34 и поместить результат в переменную PORTB
Пример №3:
1. Строка, где переменная стоит слева от =, но через знак &:
PORTB & = 0x23;
На Си означает - прочитать содержимое переменной PORTB, затем выполнить "поразрядное (побитное) логическое И" между прочитанным значением и числом 0x23 и поместить (записать, присвоить) результат в переменную PORTB.
Пример №4
2. Строка, где переменная стоит непосредственно слева от =
PORTB = 0x23;
на Си означает – не читая содержимое переменной PORTB присвоить ей значение 0x23.
Вместо & "И" (AND - только 1 и 1 дают 1) могут быть и другие побитные логические операции:
| "ИЛИ" (OR только 0 и 0 дают 0). Поразрядная дизъюнкция (ИЛИ) битовых представлений значений целочисленных операндов;
^ "иключающее ИЛИ" (XOR изменить бит напротив "1"). Поразрядная (исключение ИЛИ) битовых представлений значений целочисленных операндов;
~ "инвертирование битов" (изменить биты регистра).
С оператором присваивания используются следующие сокращения:
Табл. 2 Сокращения, используемые с оператором присваивания
ДЛИННАЯ ЗАПИСЬ СМЫСЛ СОКРАЩАЕТСЯ ДО
x = x + 1; добавить 1 x++; или ++x;
x = x - 1; вычесть 1 x--; или --x;
x = x + y; прибавить y x += y;
x = x - y; вычесть y x -= y;
x = x * y; умножить на y x *= y;
x = x / y; поделить на y x /= y;
x = x % y; остаток от деления x %= y;
x--; вычесть 1 x -= 1;
x++; добавить 1 x += 1;
Пример №5:
10010 | 1001111 – операция "ИЛИ" - только 0 и 0 дают 0
(англ. название OR )
1011111 – это результат, только биты под номером 5 в обоих числах были нули
10010 & 1001111 – операция "И" - только 1 и 1 дают 1
(англ. название AND)
10 – это результат
– только биты под номером 2 в обоих числах были единицами.
10010 ^ 1001111
"исключающее ИЛИ" – сложение по модулю два ( англ. название XOR).
1011101 – это результат.
~ 1001111 – поразрядное инвертирование , биты равные "1" станут "0" и наоборот.
110000 – это результат.
*= присваивание после умножения
Пример:
р*=2 -> р=p*2
/= присваивание после деления
Пример №6:
р/=2,2-d -> р=p/2,2-d
%= - (присваивание после деления по модулю);
Пример №7:
N%=3 -> N =N%3
+= присваивание после суммирования,
-= присваивание после вычитания,
<= присваивание после сдвига раз,рядов влево,
>>= присваивание после сдвига разрядов вправо,
&= присваивание после поразрядной конъюнкции (И),
|= присваивание после поразрядной дизъюнкции (ИЛИ),
^= присваивание после поразрядного исключающего ИЛИ.
Результатом поразрядных (побитных) логических операций: & | ^ ~, является число, которое может быть интерпретировано компилятором как "истина", если оно не ноль и "ложно", если число ноль.
Есть в Си операции которые изменяют значение переменной и без оператора присваивания:
PORTA++; Эта строчка на Си означает: взять значение переменной PORTA добавить к ней 1 и записать результат обратно в PORTA (говорят: Инкрементировать регистр PORTA).
PORTC--; Эта строчка на Си означает обратное действие! (Декрементировать - вычесть 1 из значения регистра PORTC).
Инкремент и декремент удобно использовать для изменения значения различных переменных счетчиков. Важно, помнить, что они имеют очень низкий приоритет – поэтому, чтобы быть уверенными в порядке выполнения желательно писать их отдельной строчкой программы!
В конце выражения или конструкции в программе на Си ставят точку с запятой.
Длинные выражения можно писать в несколько строк.
Когда инкремент или декремент используется в выражении, то становится важным место, где стоят два знака + или -, перед переменной или после переменной:
a=4;
b=7;
a = b++; Эта строчка на Си означает: взять значение переменной b присвоить его переменной a, затем добавить 1 к переменной b и сохранить результат в b.
В результате a будет содержать число 7, а b будет содержать число 8.
a=4;
b=7;
a = ++b; Эта строчка на Си означает: взять значение переменной b затем добавить к нему 1 и сохранить результат в b, и этот же результат присвоить a.
Теперь a будет содержать число 8 и b будет содержать число 8.
Условные и циклические операторы
if(){}else{}; идеальная конструкция, если вам нужно выполнить какую-то часть программы при наличии каких либо условий:
if (выражение) { /* делать этот код, если выражение "истина" - т.е. результат его вычисления не ноль */
}
else { /* делать этот код, если выражение "ложь" - т.е. результат его вычисления равен нулю */
};
} else { - это не обязательный элемент конструкции:
if (выражение) { /* делать этот код, если выражение "истина" - т.е. результат его вычисления не ноль */
};
while(){}; - это условный цикл - используйте если вам нужно выполнять какой-то код программы пока выполняется (существует, справедливо, не ноль) некоторое условие:
while (выражение) { /* делать этот код, если выражение "истина" - т.е. результат его вычисления не ноль. Пока выполняется этот код, выражение не проверяется на истинность! После выполнения кода происходит переход к строке while снова проверять истинность выражения.
};
Цикл while имеет вариант do – while, при котором код в { } выполняется по меньшей мере один раз, независимо от истинности условия в скобках:
do {/* сделать этот код один раз затем, если выражение есть "истина" - т.е. результат его вычисления не ноль - опять делать код с начала, и так до тех пор пока выражение является «истина» */ }
while (выражение);
for(;;){}; - этот цикл позволяет выполнить часть программы нужное число раз:
char i; /* объявление переменной для for - это обычная переменная и значит может иметь любое допустимое имя по вашему желанию */
for (i=5;i<20;i+=4) { /* код цикла for i=5 - это начальное выражение.
Число 5 просто для примера, может быть таким, как позволяет объявление переменной i, в нашем случае от 0 до 255,
i<20 - контрольное выражение. Может быть с разными операторами отношения, важно лишь, чтобы по ходу цикла оно становилось когда-то "ложью" - иначе цикл "зациклится" т.е. никогда не кончится.
i+=4 – счетчик. Обычно это i++, т.е. к переменной добавляется 1 каждый "прогон" цикла.. Но опять же, может быть таким, какое вам требуется, важно лишь достижение когда-либо условия абзацем выше! Иначе цикл станет бесконечным.
Код цикла for будет первый раз выполнен для i=5, затем по выражению i+=4, i станет 9 теперь будет проверено контрольное выражение i<20 и так как 9<20 код цикла for будет выполнен еще раз.
Так будет происходить до тех пор, пока контрольное выражение "истино". Когда оно станет "ложно" цикл for закончится и программа пойдет дальше.
};
Начальным условием - может быть любое допустимое в Си выражение, результатом которого является целое число.
Контрольное выражение - определяет до каких пор будет выполнятся цикл.
Счетчик – показывает, как изменяется начальное выражение, перед каждым новым выполнением цикла.
Циклы for (;;) и while() часто используют вот так:
while(1);
for (;;);
/* Так написанные эти циклы означают:
МК будет выполнять эту строчку пока есть питание, нет сброса и нет прерывания.
Когда возникает прерывание, программа переходит на обработчик прерывания и (если в обработчике нет перехода в другое место программы) по завершении кода обработчика опять возвращается в такой цикл. */
switch(){}; - оператор множественного выбора, позволяет вам сделать выбор из нескольких вариантов.
switch (выражение) {
case 5:
/* этот код будет выполняться, если результат вычисления выражения равен числу 5, на этом работа оператора switch закончится */
break;
case -32:
/* этот код будет выполняться, если результат вычисления выражения равен отрицательному числу -32, на этом работа оператора switch закончится */
break;
case 'G':
/* этот код будет выполняться если результат вычисления выражения равен числу, соответствующему символу G в таблице ASCII, на этом работа оператора switch закончится */
break;
default:
/* этот код будет выполняться, если результат вычисления выражения не равен ни 5, ни - 32, ни 'G', на этом работа оператора switch закончится */
};
/* switch закончен - выполняется дальнейший код программы */
case - может быть столько, сколько вам нужно, чтобы программа работала, быстрее старайтесь наиболее вероятные варианты располагать выше!
default - не обязателен.
break; - лучше писать, иначе, найдя нужный вариант, программа будет проверять и следующие условия case - напрасно тратя время.
goto - оператор безусловного (немедленного) перехода.
mesto_5: /* сюда мы попадем после выполнения строки программы goto mesto_5 */
goto mesto_1; /* перейти в то место программы, где в начале строки написано mesto_1: */
goto mesto_5; /* перейти в то место программы, где в начале строки написано mesto_5: */
mesto_1: /* сюда мы попадем после выполнения строки программы goto mesto_1 */
goto - существует наверно во всех языках и в ассемблере в том числе. Используйте его с осторожностью! Думайте, к чему может привести выполнение функций или конструкций вашей программы не до конца.
Например: Если вы покинете функцию - обработчик прерывания по goto не завершив ее, то не произойдет автоматического включения прерываний глобально - т.е. не установится бит I в регистре SREG. Этот бит устанавливается автоматически после полного выполнения функции обработки прерывания и "естественного" выхода из неё.