Содержание

Заметки по С/С++

Инициализация переменных

  // Привычная инициализация
  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. Поэтому программа не может их менять физически, а может лишь читать.

Ссылки: "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
  }

Ссылки: "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<double> v;
  for (int i = 0; i < 10; ++i)
    v.push_back(i + 3.1415);
  for( const auto &j : v )
    cout << j << " ";
        
  std::map <int, int> 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<int, 4> 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 совместим с алгоритмами STL!

std::vector - динамический массив, аллоцируется в куче - может менять длину в процессе исполнения программы

Ссылки:

Как пропустить строку при разборе текста функцией 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;
      }
  }