Лекция 12: Указатели и массивы в языке C
"Настоящие шаманы проживают в провинции Шамань, а всё остальное - это игривые колдуны."
Различие между указателями и массивами
В языке C массивы и указатели тесно связаны, но это не одно и то же. Понимание их различий важно для успешного программирования на C.
Массивы
Массив в C — это структура данных, позволяющая хранить несколько элементов одного типа данных в последовательной области памяти. Размер массива задаётся на этапе компиляции и остаётся фиксированным.
Пример объявления массива:
int arr[5]; // объявление массива из 5 элементов типа int
Размер массива нельзя изменить в процессе работы программы.
Указатели
Указатель — это переменная, которая хранит адрес другой переменной в памяти. Указатели позволяют работать с данными, расположенными в разных местах памяти, и изменять их.
Пример объявления указателя:
int *ptr; // указатель на целое число
ptr
хранит адрес переменной. Чтобы получить или изменить значение по адресу, используется операция разыменования (*
).
Ключевое различие между указателями и массивами
- Массив — область памяти, хранящая элементы одного типа, с фиксированным размером.
- Указатель — переменная, хранящая адрес. Его можно перенаправить на другую область памяти.
Пример:
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr; // указатель на первый элемент массива
printf("%d\n", arr[0]); // доступ через массив: выводит 1
printf("%d\n", *ptr); // доступ через указатель: выводит 1
Имя массива (arr
) автоматически преобразуется в указатель на первый элемент.
Массив указателей
Массив указателей — это массив, в котором каждый элемент является указателем на другой объект.
Пример:
char *arr[3] = {"Hello", "World", "C Programming"};
printf("%s\n", arr[0]); // выводит "Hello"
Каждый элемент массива arr
указывает на строку.
Строки в C
В языке C строки представляют собой массивы символов, завершающиеся нулевым символом ('\0'
).
Массивы символов
char str[] = "Hello";
str
содержит:
str[0] = 'H'
str[1] = 'e'
str[2] = 'l'
str[3] = 'l'
str[4] = 'o'
str[5] = '\0'
Указатели на строки
Строку можно представить как указатель на первый символ:
char *ptr = "Hello";
Доступ к строке через массив и указатель аналогичен.
Пример:
char str[] = "Hello";
char *ptr = "Hello";
printf("%c\n", str[0]); // выводит 'H'
printf("%c\n", *ptr); // выводит 'H'
Примеры обработки массивов и указателей
Обработка массива через указатель
При передаче массива в функцию передаётся указатель на его первый элемент.
#include <stdio.h>
void printArray(int *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%d ", *(arr + i));
}
printf("\n");
}
int main() {
int arr[5] = {10, 20, 30, 40, 50};
printArray(arr, 5);
return 0;
}
Реверс массива
Пример инвертирования массива с использованием указателей:
char z[80], s, *d, *h;
d = z;
h = &z[79];
while (d < h) {
s = *d;
*d++ = *h;
*h-- = s;
}
Циклический сдвиг массива
Сдвиг массива влево на 1 элемент:
int arr[5] = {1, 2, 3, 4, 5};
int temp = arr[0];
for (int i = 0; i < 4; i++) {
arr[i] = arr[i + 1];
}
arr[4] = temp;
Сортировка массива
Сортировка массива по возрастанию:
#include <stdio.h>
void bubbleSort(int *arr, int size) {
for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
int arr[5] = {5, 2, 9, 1, 6};
bubbleSort(arr, 5);
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
return 0;
}
Заполнение массива случайными числами
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
const int N = 10;
int arr[N];
srand(time(NULL)); // инициализация генератора случайных чисел
for (int i = 0; i < N; i++) {
arr[i] = rand() % 100; // случайное число от 0 до 99
printf("%d ", arr[i]);
}
return 0;
}
Заключение
- Массивы в C хранят элементы одного типа в последовательной области памяти.
- Указатели хранят адреса и позволяют манипулировать данными по этим адресам.
- Массив указателей используется для хранения адресов объектов, таких как строки.
- Строки — это массивы символов, заканчивающиеся нулевым символом.
- Использование указателей и массивов позволяет оптимизировать память и производительность программ.