======Заметки по С/С++======
=====Инициализация переменных=====
// Привычная инициализация
double value1 = 3.14;
// C++11, инициализация фигурными скобками не позволяется неявное преобразование.
double value2 = {3.14};
double value3 {3.14}; // uniform initialization
// Ошибка компиляции, при несовпадении типа:
int value4 = {3.14};
int value5 {3.14};
// C++11, AUTO - автоматический вывод типа при инициализации
auto value = 3.14 // double
=====Константы=====
// Константы времени компиляции - значения известны на момент компиляции
const double myConst1 {1}; // предпочтительнее использовать const перед типом данных
int const myConst2 {2}; // Допустимо в С++, но лучше использовать вариант 1
// C++11, Явное объявление константы времени компиляции, чтобы компилятор не выводил
constexpr int myConst3 {3};
constexpr int myConst4 = myConst1 + myConst2 + myConst3;
// Константа времени исполнения - не известна при компиляции
int age;
std::cin >> age;
const int usersAge (age);
// Указатель на константу
const int *pConstValue;
const int constValue = 3;
pConstValue = &constValue;
// Константный указатель на переменную
int varValue;
int *const pVarValue = &varValue;
// Возвращает указатель на символ, который нельзя менять
const char∗ strchr(const char∗ p, char c);
// Константа в параметрах функции показывает, что переменная не будет изменяться внутри функции
void printInteger(const int age)
{
std::cout << age;
}
// enum - Набор именованных целочисленных констант
enum day {sun, mon, tue, wen, thu, fri, sat};
enum number {a=54, b, c=60, d=c+5};
// Макрос (СИ), минусы:
// - не отображается при отладке
// - глобальная область видимости
// - не указан явно тип
#define MAX_COUNT 10
При программировании микроконтроллеров константные данные могут лежать в памяти ROM/FLASH. Поэтому программа не может их менять физически, а может лишь читать.
Ссылки: [[https://evileg.com/ru/post/254/|"EVILEG: C++ - Урок 003. Константы"]]
=====Перечисления, ENUM=====
// Глобальная видимость значений
enum MyColors {
Red,
Green,
Blue
}
int activeColor = Blue;
// С ограниченной областью видимости - MyColors
enum class MyColors {
Red,
Green,
Blue
}
int activeColor = MyColors::Blue;
MyColors activeColor = MyColors::Blue;
// Задание типа для хранения значения
enum class MyColors : char {
Red,
Green,
Blue
}
Ссылки: [[https://evileg.com/ru/post/279/|"EVILEG: C++ - Урок 008. Перечисления"]]
=====Массивы=====
// Объявление массива
const int N = 8;
constexpr int Square(int n) { return n * n; }
int arr[N];
int arr_sqr[Square(N)];
// Инициализация массива
int arr[3] = {1, 2, 3}; // обычная
int arr[] = {1, 2, 3}; // с выводом длины
int arr[3] {1, 2, 3}; // С++11, uniform initialization
// Объявление типа - массив
typedef int ArrInt4_t[4]; // обычное
using ArrInt4_t = int[4]; // С++11
// Получаем аналоги:
ArrInt4_t a, b;
int a[4], b[4];
// Размер
int a[4]{ 4, 3, 2, 1 };
sizeof(a) // 16,размер массива в байтах
std::size(a) // 4, количество элементов в массиве (С++17)
// C++11, Сортировка с помощью std::begin() и std::end()
std::sort(std::begin(a), std::end(a));
===C++11, Range-For-Statement===
// 1 - Значение каждого элемента массива копируется в x и выводится
int arr[] = {0,1,2,3,4,5,6,7,8,9};
for (auto x : arr)
cout << x << '\n';
for (auto x : {10,21,32,43,54,65})
cout << x << '\n';
// 2 - Обращение к элементу по ссылке (вместо копирования) - позволяет менять элемент
for (auto& x : arr)
++x; // increment
for (const auto& x : arr)
cout << x << '\n'; // Предпочтительней, если менять элемент не нужно
// Работает с контейнерами имеющими .begin() и .end()
vector v;
for (int i = 0; i < 10; ++i)
v.push_back(i + 3.1415);
for( const auto &j : v )
cout << j << " ";
std::map MAP({{1, 1}, {2, 2}, {3, 3}});
for (auto i : MAP)
std::cout << '{' << i.first << ", " << i.second << "}\n";
===Вместо массивов СИ рекомендуется использовать класс-контейнер std::array, С++11.===
// std::array - объявление с инициализацией
std::array a{1, 2, 3, 4};
for (int i = 0; i < a.size(); ++i)
std::cout << a[i] << ' ';
for (auto it = a.begin(); it != a.end(); ++it)
std::cout << *it << ' ';
for (auto t : a)
std::cout << t << ' ';
// std::vector<> - вместо динамического массива
**std::array** - это оболочка над массивом в стиле Си, но с сохранением длины массива. //(Если в функцию передавать обычный массив СИ, то теряется информация о длине и ее необходимо передавать дополнительным параметром - передается только указатель. Тоже самое при экспорте массива в глобальное пространство. При использовании std::array "потери" длины не происходит, длина хранится в объекте.)//
* Если std::array создается внутри функции, то массив аллоцируется в стеке. Необходимо разумно использовать небольшой размер стека - не выделять массивы больше нескольких килобайт!
* Если std::array объявлен вне функции, то он аллоцируется в статической памяти.
std::array совместим с алгоритмами STL!
**std::vector** - динамический массив, аллоцируется в куче - может менять длину в процессе исполнения программы
Ссылки:
* [[https://evileg.com/ru/post/265/|"EVILEG: C++ - Урок 005. Указатели, Массивы и Циклы"]]
* [[https://habr.com/ru/post/495444/|"Habr: Массивы в C++"]]
=====Как пропустить строку при разборе текста функцией sscanf (СИ)=====
Необязательный символ подавления присвоения "*": scanf() считывает входные данные в соответствии со спецификацией преобразования, но отбрасывает входные данные. Соответствующий аргумент указателя не требуется, и эта спецификация не включается в число успешных назначений, возвращаемых scanf()
Например scanf("%*s") используется пропуска комментариев в коде драйвера Linux для 1923KX028:
rd_cnt = sscanf(core_buff, "--- Scheduler 1 settings: ---\n%*s"
"Scheduler algo type: %d\n"
"Sch2 input to which Sch1 is going: %d\n"
"Weight queue of Sch2 input which Sch1 is going: %d\n"
"--- Scheduler 2 settings: ---\n%*s"
"Scheduler algo type: %d\n",
&shed0_algor,
&shed0_pos,
&shed0_weight,
&shed1_algor
);
Можно вычитывать текст построчно, параметр **%n** вернет указатель чтения в буфере:
uint8_t i;
uint8_t doClear;
for (i = 0; i < lines_count; i++) {
rd_cnt = sscanf(&core_buff[rd_pos], "Queue weight: %hhd\n%n", &doClear, &rd_pos);
if (rd_cnt == 1) {
// нашлась строка по шаблону
// делаем что хотим с doClear
break;
}
}