Перейти к содержанию

Лекция 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;
}

Заключение

  1. Массивы в C хранят элементы одного типа в последовательной области памяти.
  2. Указатели хранят адреса и позволяют манипулировать данными по этим адресам.
  3. Массив указателей используется для хранения адресов объектов, таких как строки.
  4. Строки — это массивы символов, заканчивающиеся нулевым символом.
  5. Использование указателей и массивов позволяет оптимизировать память и производительность программ.

Sex ist ein Schlacht
Liebe ist Krieg