Адреса и указатели в C/C++

Разбираем адрес памяти в C++ просто! Узнайте, как работают оператор &, указатели и ссылки, и забудьте о типичных ошибках навсегда.

Бесплатная консультация юриста

+7 (800) -02-87-29

Реклама jurik.ru

Адрес – это уникальный идентификатор ячейки памяти, в которой хранится конкретное значение. Понимание того, как работать с адресами, является фундаментом программирования на языках C и C++ (часто их называют «ЧВВ» – «C++ в Виртуальной машине»).

Содержание

  1. Что такое адрес памяти?
  2. Оператор получения адреса &
  3. Указатели: тип, объявление, инициализация
  4. Ссылки (reference) vs указатели
  5. Типичные ошибки при работе с адресами
  6. Лучшие практики

Что такое адрес памяти?

Каждая ячейка оперативной памяти имеет свой логический адрес. Этот адрес представляет собой целое число (обычно 32‑ или 64‑битное), которое процессор использует для доступа к данным.

  • Адреса задаются в шестнадцатеричной системе (например, 0x7FFDE123).
  • В пользовательском пространстве программы адреса находятся в диапазоне, выделенном операционной системой.
  • Адреса могут быть выравнены (например, переменные типа int часто находятся по адресам, кратным 4).

Оператор получения адреса &

В C/C++ оператор & возвращает адрес переменной.

int a = 10;
int *p = &a; // p хранит адрес переменной a

Важно помнить:

  • Оператор & работает только с именованными объектами (переменными, элементами массивов, полями структур).
  • Нельзя получить адрес временного значения, например: int p = &(a + 5); // ошибка.

Указатели

Указатель – это переменная, хранящая адрес другого объекта.

Объявление указателя

// Синтаксис: тип_данных  имя_указателя;
int ptr; // указатель на int
char cptr; // указатель на char
double dptr; // указатель на double

Инициализация указателя

int x = 42;
int ptr = &x; // ptr указывает на x
ptr = nullptr; // безопасное обнуление (C++11)

Разыменование указателя

Оператор позволяет получить значение по адресу.

int value = ptr; // читаем значение, на которое указывает ptr
ptr = 100; // записываем новое значение в x через указатель

Указатели и массивы

int arr[5] = {1,2,3,4,5};
int p = arr; // массив «разлагается» в указатель на первый элемент
p[2] = 10; // эквивалентно arr[2] = 10;

Ссылки (reference) vs указатели

Ссылка – это альтернативный способ доступа к объекту, но в отличие от указателя она не может быть нулевой и должна быть инициализирована при объявлении.

int a = 5;
int &ref = a; // ссылка на a
ref = 10; // меняет a
// &ref // ошибка: нельзя получить адрес ссылки (это не объект)

Сравнение:

Характеристика Указатель Ссылка
Может быть null Да Нет
Переназначаемый Да Нет (после инициализации)
Синтаксис разыменования *ptr Прямой доступ (как к переменной)

Для вывода адресов используют спецификатор %p в функции printf (C) и поток std::cout в C++.

#include <stdio.h>
int main {
 int x = 7;
 printf("Адрес x: %p
", (void*)&x);
 return 0;
}
#include <iostream>
int main {
 int x = 7;
 std::cout << "Адрес x: " << &x << std::endl;
 return 0;
}

Важно приводить указатель к типу void* при использовании printf, иначе поведение неопределено.

Типичные ошибки при работе с адресами

  • Разыменование нулевого указателя (nullptr) – приводит к segmentation fault.
  • Выход за границы массива – чтение/запись по неверному адресу.
  • Использование указателя после освобождения памяти (delete/free) – «висячий» указатель.
  • Неправильный тип указателя – например, хранить адрес int в указателе char* без приведения.
  • Потеря адреса – забыть сохранить указатель, полученный от new, и тем самым вызвать утечку памяти.

Лучшие практики

  1. Инициализировать указатели сразу после объявления: int p = nullptr;;
  2. Проверять указатель перед разыменованием:
    if (p) { / безопасно разыменовываем */ }
  3. Использовать умные указатели (std::unique_ptr, std::shared_ptr) в C++ вместо raw‑указателей, когда это возможно.
  4. Освобождать память точно в том месте, где она была выделена, и сразу обнулять указатель.
  5. Не хранить указатели в глобальных переменных без необходимости – это усложняет управление жизненным циклом.
  6. Для отладки использовать инструменты: Valgrind, AddressSanitizer, Visual Studio Debugger.

Работа с адресами в ЧВВ (C/C++) открывает доступ к низкоуровневому управлению памятью, что позволяет писать эффективный и гибкий код. Однако с большой силой приходит и большая ответственность: необходимо тщательно следить за тем, как и где вы получаете, сохраняете и освобождаете адреса.

Помните основные правила:

  • Всегда инициализируйте указатели.
  • Не разыменовывайте нулевые или «висячие» указатели.
  • Отдавайте предпочтение умным указателям в C++;
  • Тестируйте код с помощью отладчиков и статических анализаторов.

Следуя этим рекомендациям, вы сможете избежать большинства ошибок, связанных с адресами, и писать надёжный, безопасный и производительный код.


Дата публикации: 27 мая 2026 г.