Лекция 2

05.09.2025 Обновлено: 05.09.2025

Лекция 2. Указатели, массивы и строки

Указатель

  • Указатель (pointer) — переменная, диапазон значений которой состоит из адресов ячеек памяти и специального значения — нулевого адреса.
  • Значение нулевого адреса используется только для обозначения того, что указатель в данный момент не указывает ни на какую ячейку памяти.
  • Зануляем либо nullptr (предпочтительно, C++11+), либо 0 / NULL (устаревший C-стиль; NULL — это 0, что одновременно и int, и указатель — отсюда возможные неоднозначности при перегрузке функций).

void*

  • void* — указатель на любой тип.
  • Может быть явно приведён к указателю на другой тип (в C-style: (int*)ptr, в C++: static_cast<int*>(ptr)).
  • Нельзя разыменовать напрямую — сначала нужно привести к конкретному типу.

Представление в виде байтов

  • Любой указатель может быть представлен в виде массива байт!
#include <iostream>
#include <format>

void printBytes(void* ptr, size_t size) {
    uint8_t* bytes = (uint8_t*)ptr;
    for (size_t i = 0; i < size; ++i) {
        std::cout << std::format("{:08b} ", *bytes);
        ++bytes;  // увеличивает адрес на 1, смещая на след. байт
    }
    std::cout << std::endl;
}

std::format — ещё один способ организовать форматированный вывод (C++20).

Указатель на функцию

  • Синтаксис: return_type (*name)(arg_type, arg_type, ...)
  • Присваивание: name = func; или name = &func; (эквивалентно).
  • Вызов: name(args); или (*name)(args);
int add(int a, int b) { return a + b; }
int (*ptr)(int, int) = add;
int result = ptr(2, 3);  // 5