Содержание
- Типы данных, переменные, константы
- Системы счисления
- Выполнение арифметических операций
- Выполнение логических операций
- Команды ветвления (if)
- Циклы (while,for)
- Инструкция выбора (switch-case)
- Массивы, работа с массивами
- Строки
- Написание и использование функций
Типы данных, переменные, константы
Тип данных определяет диапазон допустимых значений и пространство отводимое в памяти для констант, переменных и результатов возвращаемых функциями. В таблице ниже представлены стандартные типы данных.
Тип | Название | Размер в битах | Диапазон значений |
bit | Бит | 1 | 0,1 |
char | Символ | 8 | -128..127 |
int | Целое число | 16 | -32768..32767 |
float | Вещественное число | 32 | ±1,175·10-38.. ±3,402·1038 |
long int | Длинное целое | 32 | -2147483648 .. 2147483647 |
unsigned char | Беззнаковый символ или логическое значение |
8 | 0..255 TRUE,FALSE |
unsigned int | Беззнаковое целое | 16 | 0..65535 |
unsigned long int | Беззнаковое длинное целое | 32 | 0..4294967295 |
bit | Бит | 1 | 0,1 |
Бит — базовая единица информации в вычислительной техники, все остальные типы данных строятся на основе битов. Бит может принимать одно из двух значений «1» или «0», иными словами высокий уровень сигнала или низкий уровень сигнала, есть напряжение или нет напряжения, включено или выключено 🙂
Байт — единица информации состоящая из восьми бит, с помощью байта можно представить 256 различных состояний от 0 до 255, для наглядности они представлены ниже в таблице.
Значение | Двоичное представление | Шестнадцатиричное представление |
0 | 0b00000000 | 0x00 |
1 | 0b00000001 | 0x01 |
2 | 0b00000010 | 0x02 |
… | … | … |
254 | 0b11111110 | 0xFE |
255 | 0b11111111 | 0xFF |
Тип Char. Байту данных в языке «С» соответствует тип char. Char от англ. «character», поскольку чаще всего используется для хранения символов, а точнее их ASCII-кодов, их можно посмотреть в разделе подназванием «Справочные данные». Тем не менее с его помощью можно обращаться к небольшим целым числам в диапазоне -128..127, а для типа unsigned char от 0..255, поскольку в этом случае знаковый разряд не используется, это справедливо для типа unsigned int и unsigned long int.
Переменная — именованная величина определённого типа, значение которой может изменяться в ходе выполнения программы. Для объявления переменной в языке «С» используется следующий синтаксис:
; например char x;
=; например char x = 0;
Константа — именованная величина определённого типа, значение которой не может изменяться в ходе выполнения программы.
const =; например const char x = 0xFF;
Системы счисления
Основной системой счисления в программировании для микроконтроллеров является шестнадцатиричная система счисления, но без двоичной и десятичной не обойтись. Ниже приведена таблица, в которой наглядно представлено различие этих систем.
Десятичная система | Двоичная система | Шестнадцатиричная система |
0 | 0b00000000 | 0x00 |
1 | 0b00000001 | 0x01 |
2 | 0b00000010 | 0x02 |
3 | 0b00000011 | 0x03 |
4 | 0b00000100 | 0x04 |
5 | 0b00000101 | 0x05 |
6 | 0b00000110 | 0x06 |
7 | 0b00000111 | 0x07 |
8 | 0b00001000 | 0x08 |
9 | 0b00001001 | 0x09 |
10 | 0b00001010 | 0x0A |
11 | 0b00001011 | 0x0B |
12 | 0b00001100 | 0x0C |
13 | 0b00001101 | 0x0D |
14 | 0b00001110 | 0x0E |
15 | 0b00001111 | 0x0F |
Шестнадцатиричная система счисления не заканчивается числом 0x0F, следующее число будет 0x10 и так до 0xFF.
Выполнение арифметических операций
Бинарные операции, которые поддерживает язык «C» приведены в таблице ниже.
Приоритет | Оператор | Значение |
1 | + (унарный) | Реально ничего не меняет |
1 | — (унарный) | Возвращает противоположное по знаку, равное по модулю значение |
2 | ++ (унарный) | Оператор инкремента, увеличивает значение аргумента на 1 |
2 | — (унарный) | Оператор декремента, уменьшает значение аргумента на 1 |
3 | * (бинарный) | Умножение |
3 | / (бинарный) | Деление |
3 | % (бинарный) | Остаток (деление по модулю) |
4 | + (бинарный) | Сложение |
4 | — (бинарный) | Вычитание |
5 | =, *=, %=, +=, -= | Операторы присвоений (специальные) |
Примеры использования арифметических операторов.
char i=10;
i+; //Реально ничего не меняет, поэтому на практике не используется.
i-; //Значение переменной «i»поменяет свой знак, в данном случае станет «-10».
i++; //Этот оператор прибавит 1 к переменной «i», т.е. эквивалентное выражение i=i+1;
i—; //Этот оператор вычтет 1 из переменной «i», т.е. эквивалентное выражение i=i-1;
i=i*10; //В этом выражении значение переменной «i» умножется на 10, а полученный результат перезапишется в
переменную «i», т.е. в результате «i» будет равно 100.
i=i/10; //В этом выражении думаю всё должно быть понятно.
i=15%4; //Это выражение вычисляет остаток, т.е. 15/4=12 с остатком 3 (12 + 3 = 15), вот этот остаток и бует результатом
данного выражения.
i=i-2; i=i+3; //Думаю эти выражения в комментариях не нуждаются.
Давайте подробнее остановимся на операторах присвоения.
i=0b00000001; //Переменной «i» присвоено значение «1» (двоичная система счисления)
i=1; //Переменной «i» присвоено значение «1» (десятичная система счисления)
i=0x01; //Переменной «i» присвоено значение «1» (шестнадцатиричная система счисления)
Выполнение логических операций
Для принятия решений в программах просто необходимо использовать логические операторы.
Простые логические операции приведённые ниже в таблице могут возвращать два значения true(истина) и false(ложь).
Оператор | Значение |
== | Знак равенства, очень часто путают со знаком присвоения «=». Выражение будет истино, если левая и правая чато выражения будут равны. |
!= | Знак неравенства Выражение будет истино, если левая и правая чато выражения будут НЕ равны. |
>, < | Больше, меньше; истинно, когда значение левого выражения больше (или меньше) значения правого |
>=,Выражение истинно, если левая часть «>» или «==» правой, или « | |
&& | «И», истинно, если аргументы И слева И справа являются истиной |
|| | «ИЛИ», истинно, если аргументы ИЛИ слева ИЛИ справа являются истиной |
! | «НЕ», истинно, если аргумент принимает ложное значение |
Давайте рассмотрим несколько простых примеров. Возьмём две переменные одного типа и сравним их.
Пример 1:
//В языке С такая строчка обозначает комментарий, т.е. на ход выполнения программы не влияет.
char a=1; //Объявили переменную «a» и присвоели ей значение.
char b=1; //Объявили переменную «b» и присвоели ей значение.
Теперь подставляем логический оператор, например, оператор равенстава «==».
a == b //a равно b?
Результатом этого выражения будет истина (true), т.к. 1 == 1.
Пример 2:
char a=1;
char b=0;
a && b
Результатом этого выражения будет ложь (false), т.к. b == 0. «0» в логических конструкциях обозначает ложь(false), т.е. если выражение равно нулю, оно ложно.
Пример 3:
char a=1;
char b=0;
a || b
Результатом этого выражения будет истина (true), т.к. одно из аргументов истинно (a == 1).
Теперь самостоятельно попробуйте написать выражения используя другие логически операторы.
После того как освоите простые логические выражения, попробуйте составить сложные, они отличаются лиш тем что в левой и правой частях стоит не просто переменная а целое выражение.
Пример:
char a=1;
char b=0;
char c=0;
char d=0;
(a > b) || (c != d)
Теперь давайте разберёмся. Между выражениями стоит знак ИЛИ «||», это значит что если одна из частей выражения (левая или правая) после вычисления даст истину, то итоговый ответ будет истинным. Теперь проверяем левую часть «a > b», это истина, левую часть можно не проверять, т.к. результат уже известен.
Команды ветвления (if)
Проще всего управлять ходом программы с помощью инструкции ветвления, которая позволяет программе, в зависимости от результата логического выражения, решить, по какому пути выполнения инструкций следует двигаться дальше.
В языке С оператор условного перехода реализуется с помощью инструкции «if», if с англ. «если». Рассмотрим простейшие примеры.
Пример 1:
char a=1;
char b=0;
if(a > b){ //Если «a» больше чем «b»
//инструкции которые должны быть выполнены
}
else{
//инструкции которые должны быть выполнены если «a» МЕНЬШЕ «b», т.е. выражение «a > b» ложно.
}
Пример 2:
Инструкцию «if» также можно использовать без инструкции «else».
if(истина){
//инструкции которые должны быть выполнены
}
Циклы (while,for)
Самый простой цикл можно организовать с помощью оператора while. Он выглядит таким образом:
while(условие){
//Этот код выполняется повторно,пока условие остаётся истинно
}
Перед тем как выполнить код, оператор while проверяет условие, если условие не удовлетворяется, код выполняться не будет.
do{
//Этот код выполняется повторно,пока условие остаётся истинно
}while(условие);
Отличие этого цикла от предыдущего состоит в том, что перед тем как проверить условие, код выполниться один раз, т.е. сначала выполняется цикл, потом проверяется условие, если условие истинно, то цикл выполниться ещё раз и ещё раз проверится условие.
Существуют бесконечные циклы, которые повторяются снова и снова, получить бесконечный цикл очень легко, нужно чтобы условие цикла всегда было «истинным» значением, например «1» это истина. Один из наиболее часто используемых бесконечных циклов я привёл ниже.
while(1){
//Инструкции, которые будут выполняться бесконечно
}
Теперь рассмотрим оператор for. Этот оператор используется в паре с переменной, любой, возьмём например переменную «i».
Теперь представим что по условию задачи нам нужно чтобы цикл повторился 10 раз, тогда синтаксис условия будет следующим:
for(i=0;i
//Инструкции для выполнения
}
Рассмотрим выражение из которого сотоит условие цикла, оно состоит из трёх частей, в первой части мы присваиваем начальное значение, с которого начнётся отсчёт (например i=0;), во второй части устанавливаем само условие, используя логические ператоры, в данном случае i, а в третьей части прописывается условие, которое увеличивает или уменьшает цикл, в основном используют инкримент или декримент (i++; i—;).
Инструкция выбора (switch-case)
Инструкция switch-case эффективна, если существует необходимость выбора при ограниченном количестве возможных вариантов. Она похожа на усложненную инструкцию if, которая вместо проверки одного условия анализирует множество разных возможностей:
switch (выражение)
{
case c1:
//переходим сюда, если выражение == c1
break;
case c2:
//переходим сюда, если выражение == с2
break;
default:
//если ни одно условие не выполнено, переходим сюда
}
Значением выражения должно быть целое число {int, long или char); cl, с2 и т.д. должны быть константами.Инструкция switch выполняется следующим образом: сначала вычисляется значение выражения, а затем оно сравнивается с константами, указанными после служебного слова case. Если константа соответствует значению выражения, то программа передает управление этой ветви. Если ни один вариант не подходит, выполняется условие default.Для выхода из инструкции switcn необходимо использовать команды break, иначе управление будет переходить от одного случая к следующему.
Массивы, работа с массивами
Массив — это тип данных, который используется для представления последовательности однотипных значений.
Массивы объявляются подобно обычным переменным, с указанием в квадратых скобках размерости (количества элементов в массиве).
int digits[10] //Массив из десяти элементов типа int
char str[10] //Массив из десяти символов (строка)
Доступ к элементам массива реализуется с помощью индекса(порядкового номера элемента, начиная с 0).
digits[0]=0; //Присвоили первому значению массива число 0
str[0]=’А’; //Присвоили первому элементу строки значение «A»
Многомерные массивы
Язык С допускает использование многомерных массивов. Простыми словами обычный массив это строка(т.е. все элементы располагаются строкой), а многомерный это строки и столбцы, смотрите пример ниже и всё станет понятно.
char a[]={1,2,3,4,5,6,7,8} //одномерный массив
char b[2][3]={ {1,2,3}, //Двухмерный массив, 2 строки по 3 элемента в каждой
{4,5,6} };
Строки
Строка в языке С — это массив типа char
Пример объявления строки(символьного массива):
char stroka[10]=»Hello»;
В данном примере размер массива — 10 символов (от 0 до 9), а длина строки «Hello» — 5 символов, посмотрите как произведётся запись символов в массив:
stroka[0]=’H’;
stroka[1]=’e’;
stroka[2]=’l’;
stroka[3]=’l’;
stroka[4]=’o’;
Остальные байты массива остануться пустыми. Если массив строковый, то его размерность можно не указывать, компилятор автоматически будет выделять место по мере необходимости.
char stroka[10];
char stroka[];
Теперь когда строка записана в массив, мы можем обратиться к конкретному символу и изменить его, например давайте изменим символ «H» на символ «s»:
stroka[0]=’s’;
Хочу обратить ваше внимание на кавычки в которых заключена строка или символ, они отличаются:
char stroka[10]=»Hello»; //Когда присваеваем строку кавычки двойные
stroka[0]=’H’; //Когда присваеваем символ, перед и после символа ставим апострофы
Написание и использование функций
Функция — это подпрограмма или микропрограмма, входящая в состав основного цикла программы. Функции очень удобны в использовании, проще «составлять» из функций программу, чем прописывать один и тот же код по нескольку раз.
Давайте рассмотрим строение функции в общем виде:
имя функции
Аргументами функции называются значения, которые передаются функции при вызове. В возвращаемом значении указывается результат, который функция возвращает по
окончании работы. Функции могут иметь не один аргумент, в этом случае аргументы разделяются запятыми.
Пример:
char demo(char a,b){
char c; //Вспомогательная переменная.
c = (a + b)+(2 * a); //Любое необходимое выражение.
return c; //Строка, которая возвращает значение, она обязательна должна присутствовать
}
Тип возвращаемого значения (в данном случае результата вычисления) — char, тип аргументов — char, имя функции — summa, вы можете использовать любое, кроме зарезервированных слов компилятора Си. Смотрете их в help’е компилятора.
Давайте рассмотрим пример и вы убедитесь что лучше один раз посидеть и подумать над грамотным написанием функции, чем потом заниматься копипастом 🙂
char x = 0;
char y = 0;
char demo(char a,b){
char c;
c = (a + b)+(2 * a);
return c;
}
x = demo(10,2);
y = demo(x,15);
z = demo(x,y);
Теперь рассмотрим пример эквивалентный, но без использования функции «demo».
char x = 0, y = 0, z = 0; //Так можно объявлять переменные одного типа.
x = (10 + 2) + (2 * 10);
y = (x + 15) + (2 * x);
z = (x + y) + (2 * x);
В этом примере мы постоянно переписываем одно и тоже выражение, только подставляем другие аргументы, согласитесь неудобно если это вражение встречается в программе много раз.
И аргументы, и возвращаемое значение функции необязательны. Если что-то отсутствует, вместо него используется ключевое слово void. Значит, если вместо списка аргументов используется void, то при вызове функция не получает никаких аргументов, например:
void main(void){};
Функция «main» ничего не возвращает и у неё нет аргументов, при её вызове, она выполнится только один раз, если конечно не вставить в неё какой нибудь цикл и/или условие.
char demo2(void){};
Функция «demo2» возвращает значение символьного типа, но не имеет аргумента, например это может быть функция которая возвращает псевдослучайное значение, в диапазоне типа char.
Функции без аргументов используются редко, так как связь с такими функциями односторонняя, т.е. осуществляется только посредством возвращаемых значений.
Давайте рассмотрим структуру программы на «С».
void main(void){
while(1){
//Ваша программа
}
}
Функция main это основная функция, она присутствует в любой программе, в теле этой функции обычно прописывается бесконечный цикл, в котором будет исполняться ваша программа.
Все функции которые вы будете использоваться в вашей программе, должны объявляться ДО функции «main», с этим вы встретитесь когда будете подробнее изучать компиляторы.