Урок 5: Указатели в C

Указатели — одна из самых мощных и сложных концепций в C. Указатель — это переменная, которая хранит адрес другой переменной в памяти. Они позволяют эффективно работать с памятью и создавать сложные структуры данных.

Основы указателей

Указатель объявляется с помощью символа *, а оператор & возвращает адрес переменной.

#include <stdio.h> int main() { int number = 42; int *ptr; // Объявление указателя на int ptr = &number; // ptr теперь хранит адрес number printf("Значение number: %d\n", number); printf("Адрес number: %p\n", &number); printf("Значение ptr: %p\n", ptr); printf("Значение по адресу ptr: %d\n", *ptr); return 0; }
  • int *ptr — объявление указателя на целое число
  • &number — оператор взятия адреса
  • *ptr — оператор разыменования (получение значения по адресу)
  • %p — спецификатор формата для вывода адреса

Изменение значений через указатели

Указатели позволяют изменять значения переменных через их адреса.

#include <stdio.h> int main() { int x = 10; int *ptr = &x; printf("До изменения: x = %d\n", x); *ptr = 20; // Изменяем значение x через указатель printf("После изменения: x = %d\n", x); return 0; }
  • *ptr = 20 изменяет значение переменной x
  • Указатель даёт прямой доступ к памяти переменной

Передача указателей в функции

Указатели позволяют функциям изменять значения переменных из вызывающей функции.

#include <stdio.h> void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } int main() { int x = 5, y = 10; printf("До обмена: x = %d, y = %d\n", x, y); swap(&x, &y); printf("После обмена: x = %d, y = %d\n", x, y); return 0; }
  • Функция swap принимает указатели на int
  • Вызов swap(&x, &y) передаёт адреса переменных
  • Функция может изменять оригинальные значения x и y

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

В C имя массива — это указатель на его первый элемент.

#include <stdio.h> int main() { int arr[] = {10, 20, 30, 40, 50}; int *ptr = arr; // Указатель на первый элемент // Доступ к элементам через указатель for (int i = 0; i < 5; i++) { printf("arr[%d] = %d, *(ptr + %d) = %d\n", i, arr[i], i, *(ptr + i)); } return 0; }
  • arr и &arr[0] — одно и то же
  • *(ptr + i) эквивалентно arr[i]
  • Арифметика указателей: ptr + 1 указывает на следующий элемент

Динамическое выделение памяти

Функции malloc и free позволяют выделять и освобождать память во время выполнения программы.

#include <stdio.h> #include <stdlib.h> int main() { int n = 5; int *arr = (int*)malloc(n * sizeof(int)); if (arr == NULL) { printf("Ошибка выделения памяти\n"); return 1; } // Заполнение массива for (int i = 0; i < n; i++) { arr[i] = i * 10; } // Вывод массива for (int i = 0; i < n; i++) { printf("%d ", arr[i]); } free(arr); // Освобождение памяти return 0; }
  • malloc(size) — выделяет блок памяти указанного размера
  • sizeof(int) — возвращает размер типа в байтах
  • free(ptr) — освобождает выделенную память
  • Всегда проверяйте результат malloc на NULL

Нулевой указатель

Нулевой указатель не указывает ни на какой объект.

#include <stdio.h> int main() { int *ptr = NULL; // Инициализация нулевым указателем if (ptr == NULL) { printf("Указатель не инициализирован\n"); } // Использование указателя только после проверки int x = 100; ptr = &x; if (ptr != NULL) { printf("Значение: %d\n", *ptr); } return 0; }
  • NULL — специальное значение для неинициализированных указателей
  • Всегда проверяйте указатели перед разыменованием
  • Обращение к NULL-указателю вызывает ошибку сегментации
🏠 На главную Следующий урок