Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Материалы для подготовки к экзамену по ОП.docx
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
298 Кб
Скачать
☆

Арифметика указателей

  • Во-первых, указателю нужен тип для того, чтобы корректно работала операция разыменования (получения содержимого по адресу). Если указатель хранит адрес переменной, необходимо знать, сколько байт нужно взять, начиная от этого адреса, чтобы получить всю переменную.

  • Во-вторых, указатели поддерживают арифметические операции. Для их выполнения необходимо знать размер.

операция + N сдвигает указатель вперёд на N*sizeof(тип) байт.

Например, если указатель int *p; хранит адрес CC02, то после p += 10; он будет хранить адрес СС02 + sizeof(int)*10 = CC02 + 28 = CC2A (Все операции выполняются в шестнадцатиричном формате). Пусть мы создали указатель на начало массива. После этого мы можем "двигаться" по этому массиву, получая доступ до отдельных элементов.

#include <conio.h>

#include <stdio.h>

void main() {

int A[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

int *p;

p = A;

printf("%d\n", *p);

p++;

printf("%d\n", *p);

p = p + 4;

printf("%d\n", *p);

getch();

}

Заметьте, каким образом мы получили адрес первого элемента массива

p = A;

Массив, по сути, сам является указателем, поэтому не нужно использовать оператор &. Мы можем переписать пример по-другому

p = &A[0];

Получить адрес первого элемента и относительно него двигаться по массиву.

Кроме операторов + и - указатели поддерживают операции сравнения. Если у нас есть два указателя a и b, то a > b, если адрес, который хранит a, больше адреса, который хранит b.

#include <conio.h>

#include <stdio.h>

void main() {

int A[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

int *a, *b;

a = &A[0];

b = &A[9];

printf("&A[0] == %p\n", a);

printf("&A[9] == %p\n", b);

if (a < b) {

printf("a < b");

} else {

printf("b > a");

}

getch();

}

Если же указатели равны, то они указывают на одну и ту же область памяти.

Указатель на указатель

Указатель хранит адрес области памяти. Можно создать указатель на указатель, тогда он будет хранить адрес указателя и сможет обращаться к его содержимому. Указатель на указатель определяется как

<тип> **<имя>;

Очевидно, ничто не мешает создать и указатель на указатель на указатель, и указатель на указатель на указатель на указатель и так далее. Это нам понадобится при работе с двумерными и многомерными массивами. А вот простой пример, как можно работать с указателем на указатель.

#include <conio.h>

#include <stdio.h>

#define SIZE 10

void main() {

int A;

int B;

int *p;

int **pp;

A = 10;

B = 111;

p = &A;

pp = &p;

printf("A = %d\n", A);

*p = 20;

printf("A = %d\n", A);

*(*pp) = 30; //здесь скобки можно не писать

printf("A = %d\n", A);

*pp = &B;

printf("B = %d\n", *p);

**pp = 333;

printf("B = %d", B);

getch();

}