В C++ и в Arduino IDE каждая переменная, аргумент функции и возвращаемое значение функции должны иметь тип, чтобы их можно было скомпилировать.
Вы можете создать собственный тип, определив classstruct. Тип определяет объем памяти, выделяемой для переменной и способы её использования.
C++ — это строго типизированный язык, который также является статически типизированным; каждый объект имеет тип и этот тип никогда не изменяется. При объявлении переменной в коде необходимо явно указать его тип или использовать ключевое слово auto, чтобы указать компилятору выводить тип из инициализатора.
При объявлении функции в коде необходимо указать тип каждого аргумента и возвращаемое функцией значение, или void если значение не возвращается. Исключением является использование шаблонов функции, которые допускают аргументы произвольных типов.
Иногда в C++ применяют операции преобразования типов, которые бывают необходимы, но также являются потенциальными источниками потери данных или других ошибок.
При объявлении переменной типа POD настоятельно рекомендуется инициализировать ее, т. е. указать начальное значение. Пока переменная не инициализирована, она имеет "мусорное" значение, определяемое значениями битов, которые ранее были установлены в этом месте памяти.
В отличие от некоторых других языков, в C++ нет универсального базового типа, от которого наследуются все остальные типы. Язык включает множество фундаментальных типов, также известных как встроенные типы (базовые).
Числа в C++
В Arduino IDE мы можем использовать целые (литералы, целочисленные константы) десятичные (Decimal), двоичные (Binary), шестнадцатеричные (Hexadecimal), восьмеричные (Octal), целые со знаком, вещественные числа, с плавающей запятой и с экспонентой.
Система счисления | Префикс | Пример | Допустимые символы |
---|---|---|---|
10 (десятичная) | 32768 | 0123456789 | |
2 (двоичная) | 0b | 01 | |
8 (восьмеричная) | 0 | 01234567 | |
16 (шестнадцатеричная) | 0x | 0123456789ABCDEF |
Суффиксы U и L
По умолчанию целочисленная константа рассматривается как int с соответствующими ограничениями значений. Чтобы указать целочисленную константу с другим типом данных, добавьте к ней:
- u или U для преобразования константы в беззнаковый формат данных. Пример: 33U
- l или L, для преобразования константу в длинный формат данных. Пример: 100000L
- ul или UL, для преобразования константу в беззнаковую длинную константу. Пример: 32767UL
Переменные
Переменная – это место хранения данных. Она имеет имя, тип, адрес и значение.
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display(128, 64, &Wire, 7);
int x1 = -32768;
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.fillScreen(1);
display.setTextSize(2);
display.setTextColor(0, 1);
display.print (x1);
display.display();
}
void loop() {
}
Скетч. 1. Программа «Вывод значения переменной на дисплей SSD1306».
Задание №1. Попробуйте с помощью программы Скетч. 1 вывести на дисплей число 32769.
/*
ASCII table
Prints out byte values in all possible formats:
- as raw binary values
- as ASCII-encoded decimal, hex, octal, and binary values
For more on ASCII, see http://www.asciitable.com and http://en.wikipedia.org/wiki/ASCII
The circuit: No external hardware needed.
created 2006
by Nicholas Zambetti <http://www.zambetti.com>
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/ASCIITable
*/
int thisByte = 33;
void setup() {
Serial.begin(9600);
while (!Serial) {
}
Serial.println("ASCII Table ~ Character Map");
}
void loop() {
Serial.write(thisByte);
Serial.print(", dec: ");
Serial.print(thisByte);
Serial.print(", hex: ");
Serial.print(thisByte, HEX);
Serial.print(", oct: ");
Serial.print(thisByte, OCT);
Serial.print(", bin: ");
Serial.println(thisByte, BIN);
if (thisByte == 126) {
while (true) {
continue;
}
}
thisByte++;
}
Скетч. 2. Программа «Вывод ASCII таблицы в последовательный порт».
Область видимости переменных
ппаыр
Типы данных
dhgh
Тип | Сокр. | Название | Байт | Диапазон | |
---|---|---|---|---|---|
void | 0 | ||||
boolean | bool | Булево | 1 | false | true |
char | Символьное | 1 | -128 | 127 | |
unsigned char | Беззнаковое символьное | 1 | 0 | 255 | |
byte | Байт | 1 | 0 | 255 | |
integer | int | Целое | 2 | -32 768 | 32 768 |
unsigned int | Беззнаковое целое | 2 | 0 | 65535 | |
word | Слово | 2 | 0 | 65535 | |
short | Целое | 2 | |||
long | Длинное | 4 | -2147483648 | 2147483647 | |
unsigned long | Беззнаковое длинное | 4 | 0 | 4294967295 | |
float | С плавающей запятой | 4 | -3,4028235E+38 | 3,4028235E+38 | |
double | С плавающей запятой с двойной точностью | Зависит от используемого микроконтроллера | |||
array | Массив | ||||
string | Текстовая строка или массив char | ||||
String | Объект класса String | ||||
size_t |
Табл. 1. Типы данных, широко используемые в Arduino проектах.
boolean
Логический (булевый) тип данных — boolean. Может принимать одно из двух значений true или false. boolean занимает в памяти один байт.
char
Переменная типа char занимает 1 байт памяти и может хранить один алфавитно-цифровой символ (литеру). При объявление литеры используются одиночные кавычки: 'A' (двойные кавычки используется при объявлении строки символов - тип string: "ABC").
Символ хранится в памяти как число, соответствующее коду символа в таблице кодировки символов ASCII. Т.к. символ хранится как число в памяти над ним возможно производить арифметические действия (например, 'A' + 1 будет 66, т.к. ASCII код для 'A' - 65).
Тип char знаковый тип, т.е. число (код) хранящийся в памяти может принимать значения от -128 до 127. Если необходим беззнаковая однобайтовая переменная, используйте тип byte.
byte
Описание типа
Тип данных byte 8-ми битное беззнаковое целое число, в диапазоне 0..255.
int
Описание типа данных
Тип данных int (от англ. integer - целое число) один их наиболее часто используемых типов данных для хранения чисел. int занимает 2 байта памяти, и может хранить числа от -32 768 до 32 767 (от -2^15 до 2^15-1)
Для размещения отрицательных значений int использует, так называемый, дополнительный код представления числа. Старший бит указывает на отрицательный знак числа, остальные биты инвертируются с добавлением 1.
Arduino компилятор сам заботиться о размещение в памяти и представление отрицательных чисел, поэтому арифметические действия над целыми числами производятся как обычно.
unsigned int
Описание типа
Тип данных unsigned int - беззнаковое целое число, также как и тип int (знаковое) занимает в памяти 2 байта. Но в отличие от int, тип unsigned int может хранить только положительные целые числа в диапазоне от 0 до 65535 (2^16)-1).
Отличие кроется в том как unsigned int использует старший бит, иногда называемый знаковый бит. Если старший бит равен 1, то для типа int компилятор Arduino считает, что это число отрицательное, а остальные 15 bit несут информацию о модуле целого числа в дополнительного кода представления числа, в то время как unsigned int использует все 16 бит для хранения модуля числа.
word
Описание типа
Тип данных word хранит 16-битное, не содержащее знака, число от 0 до 65535. Тоже самое, что unsigned int — (беззнаковое целое число).
long
Описание типа
Тип данных long используется для хранения целых чисел в расширенном диапазоне от -2,147,483,648 до 2,147,483,647. long занимает 4 байта в памяти.
unsigned long
Описание типа
Unsigned long используется для хранения положительных целых чисел в диапазоне от 0 до 4,294,967,295 (2^32 - 1) и занимает 32 бита (4 байта) в памяти.
float
Описание типа
Тип данных float служит для хранения чисел с плавающей запятой. Этот тип часто используется для операций с данными, считываемыми с аналоговых входов. Диапазон значений — от -3.4028235E+38 до 3.4028235E+38. Переменная типа float занимает 32 бита (4 байта) в памяти.
Тип float имеет точность 6-7 знаков, имеются ввиду все знаки, а не только мантисса. Обычно для увеличения точности используют другой тип - double, но на платформе Arduino, double и float имеют одинаковую точность.
Хранение в памяти чисел с плавающей точкой в двоичной системе обуславливает потерю точности. Так, например, 6.0 / 3.0 не обязательно равен 2.0. Сравнивая два числа с плавающей точкой следует проверять не точное равенство, а разницу между этими числами, меньше ли она некого выбранной малого порога.
Следует также учитывать, что арифметические операции над числами с плавающей запятой выполняются существенно медленнее, чем над целыми.
double
Описание типа данных
Тип данных double, в отличие от большинства языков программирования, имеет ту же точность, что и тип float и занимает также 4 байта памяти.
Тип double поддерживается в Arduino для совместимости кода с другими платформами.
string - текстовые строки
Описание
Текстовые строки в Ардуино объявляются как массив (array) типа char (символов - литер), оканчивающийся символом "конца строки".
Синтаксис
Ниже приведены варианты объявления и присвоения строк:
char Str1[15];
char Str2[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o'};
char Str3[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o', '\0'};
char Str4[ ] = "arduino";
char Str5[8] = "arduino";
char Str6[15] = "arduino";
Возможны следующие варианты объявления текстовых строк:
Объявить массив символов без присваивания значений — Str1
Объявить массив символов и присвоить значения всем элементам, кроме последнего, компилятор Arduino автоматически добавит символ конца строки, как в Str2
Явно объявить завершающий символ, как в Str3
Инициализировать массив строковой константой в двойных кавычках. Компилятор автоматически задаст требуемый размер на массив, равный количеству символов плюс завершающий символ, как в варианте Str4
Инициализировать массив с явным заданием размера и присвоением строковой константы, строка Str5
Инициализировать массив с явным заданием дополнительного размера (с запасом), фактически превышающего размер строковой константы при начальном присвоение, как в варианте Str6
Символ окончания строки
Обычно строки оканчиваются нулевым символом (код 0 в ASCII). Это позволяет функциям (таким как Serial.print()) выявлять окончание строки. В противном случае могут считаться байты памяти, не принадлежащие переменной.
Массивы символов, выделяемый под строку, должен иметь один дополнительный элемент для символа конца строки. Именно поэтому Str2 и Str5 должны иметь 8 символом, хотя "arduino" 7 символов — последнему элементу автоматически присваивается символ окончания строки.
Технически возможно объявить строку без символа окончания строки, например, объявить длину массива равной 7 для Str2. Это приведет к некорректной работе функций, оперирующих строками.
Одинарные и двойные кавычки
Строки всегда объявляются внутри двойных кавычек ("Abc"). Символы — внутри одинарных ('A')
Инициализация длинных строк
Длинные строки могут быть объявлены так:
char myString[] = "This is the first line"
" this is the second line"
" etcetera";
Массивы строк
При работе с большими объемами текстовой информации, например в проектах с LCD дисплеем, бывает удобно использовать массивы строк. Так как строки сами по себе массивы, массивы строк будет двумерным массивом.
В примере ниже, символ звездочки после объявления типа "char*" указывает на то, что это массив указателей. Это необходимо для задания двумерного массива. В данном случае не требуется понимания всех тонкостей работы с указателями.
String
String класс появился в версии Arduino 0019. Этот класс позволяет хранить и манипулировать текстовыми строками, по сравнению с string (массивом символов) класс String предоставляет удобные функции для работы со строками, такие как поиск вхождения в строку, объединение строк и др. Класс String занимает несколько больше места в памяти, чем массив символов string.
Обратите внимание при обращение к классу String — он пишется с заглавной S. Массив символов string — с прописной s. Строковые константы, записанные в "двойных кавычка" интерпретируются компилятором как массив символов, а не объект класса String.
Функции
String()
charAt()
compareTo()
concat()
endsWith()
equals()
equalsIgnoreCase()
getBytes()
indexOf()
lastIndexOf()
length()
replace()
setCharAt()
startsWith()
substring()
toCharArray()
toLowerCase()
toUpperCase()
trim()
Массивы
Массивы (arrays) — именованный набор однотипных переменных, с доступом к отдельным элементам по их индексу.
Объявление массивов
Ниже приведены несколько корректных вариантов объявления массивов:
int myInts[6];
int myPins[] = {2, 4, 8, 3, 6};
int mySensVals[6] = {2, 4, -8, 3, 2};
char message[6] = "hello";
Массив может быть объявлен без непосредственной инициализации элементов массива, как в случае массива myInts.
Массив myPins был объявлен без явного задания размера. Компилятор сам посчитает фактическое количество элементов и создаcт в памяти массив необходимого размера.
Размер может быть задан явно, одновременно с инициализацией элементов массива. Обратите внимания, что при создании массива типа char, необходим дополнительный элемент массива для нулевого символа. Подробнее см. строки.
Доступ к элементам массива
Индексация массива начинается с 0. Это значит, что для массива с 10-тью элементами, индекс 9 будет последним:
int myArray[10]={9,3,2,4,3,2,7,8,9,11};
// myArray[0] первый элемент, содержит 9
// myArray[9] последний элемент, содержит 11
// myArray[10] это неверно возможно возвращение произвольного значения из области памяти не относящийся к массиву
Присваиваем значение элементу массива:
mySensVals[0] = 10;
Возвращаем значение элемента массива:
x = mySensVals[4];
Массивы и FOR циклы
Чаще всего для перебора элементов цикла используется цикл for, счетчик цикла используется как индекс для доступа к каждому элементу массива. Например, для вывода массива через Serial порт можно использовать следующий код:
int i;
for (i = 0; i < 5; i = i + 1) {
Serial.println(myPins[i]);
}
void
Ключевое слово void используется при объявлении функций, если функция не возвращает никакого значение при ее вызове (в некоторых языках программирования такие функции называют процедурами).