Урок 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-указателю вызывает ошибку сегментации