Этот сайт использует cookies. Продолжение работы с сайтом означает, что Вы согласны!
Доступ к элементам массива с помощью указателя
После определения массива в переменной сохраняется адрес первого элемента. Иными словами, название переменной является указателем, который ссылается на первый элемент массива. Поэтому доступ к элементу массива может осуществляться как по индексу, указанному внутри квадратных скобок, так и с использованием адресной арифметики. Например, следующие инструкции вывода являются эквивалентными:
int arr[3] = {1, 2, 3};
std::cout << arr[1] << std::endl; // 2
std::cout << *(arr + 1) << std::endl; // 2
std::cout << *(1 + arr) << std::endl; // 2
std::cout << 1[arr] << std::endl; // 2
Последняя инструкция может показаться странной. Однако, если учесть, что выражение 1[arr]
воспринимается компилятором как *(1 + arr)
, то все встанет на свои места.
При указании индекса внутри квадратных скобок, каждый раз производится вычисление адреса соответствующего элемента массива. Чтобы сделать процесс доступа к элементу массива более эффективным объявляют указатель и присваивают ему адрес первого элемента. Далее для доступа к элементу просто перемещают указатель на соответствующий элемент. Пример объявления указателя и присваивания ему адреса первого элемента массива:
int *p = nullptr;
int arr[3] = {1, 2, 3};
p = arr;
std::cout << *p << std::endl; // 1
std::cout << *(p + 1) << std::endl; // 2
std::cout << *(p + 2) << std::endl; // 3
Обратите внимание на то, что перед названием массива не указывается оператор &
, так как название переменной содержит адрес первого элемента. Если использовать оператор &
, то необходимо дополнительно указать индекс внутри квадратных скобок:
p = &arr[0]; // Эквивалентно: p = arr;
Таким же образом можно присвоить указателю адрес произвольного элемента массива, например, третьего:
int *p = nullptr;
int arr[3] = {1, 2, 3};
p = &arr[2]; // Указатель на третий элемент массива
std::cout << *p << std::endl; // 3
Чтобы получить значение элемента, на который ссылается указатель, необходимо произвести операцию разыменования. Для этого перед названием указателя добавляется оператор *
. Пример:
std::cout << *p << std::endl;
Указатели часто используются для перебора элементов массива. В качестве примера создадим массив из трех элементов, а затем выведем значения с помощью цикла for
:
const int ARR_SIZE = 3;
int *p = nullptr, arr[ARR_SIZE] = {10, 20, 30};
// Устанавливаем указатель на первый элемент массива
p = arr; // Оператор & не указывается!!!
for (int i = 0; i < ARR_SIZE; ++i) {
std::cout << *p << std::endl;
++p; // Перемещаем указатель на следующий элемент
}
p = arr; // Восстанавливаем положение указателя
В первой строке объявляется константа ARR_SIZE
, в которой сохраняется количество элементов в массиве. Если массив используется часто, то лучше сохранить его размер как константу, так как количество элементов нужно будет указывать при каждом переборе массива. Если в каждом цикле указывать конкретное число, то при изменении размера массива придется вручную вносить изменения во всех циклах. При объявлении константы достаточно будет изменить ее значение один раз при инициализации.
В следующей строке объявляется указатель на тип int
и массив. Количество элементов массива задается константой ARR_SIZE
. При объявлении массив инициализируется начальными значениями.
Внутри цикла for
выводится значение элемента на который ссылается указатель, а затем значение указателя увеличивается на единицу (++p;
). Обратите внимание на то, что изменяется адрес, а не значение элемента массива. При увеличении значения указателя используются правила адресной арифметики, а не правила обычной арифметики. Увеличение значения указателя на единицу означает, что значение будет увеличено на размер типа. Например, если тип int
занимает 4
байта, то при увеличении значения на единицу указатель вместо адреса 0x0012FF30
будет содержать адрес 0x0012FF34
. Значение увеличилось на 4
, а не на 1
. В нашем примере вместо двух инструкций внутри цикла можно использовать одну:
std::cout << *p++ << std::endl;
Выражение p++
возвращает текущий адрес, а затем увеличивает его на единицу. Символ *
позволяет получить доступ к значению элемента по указанному адресу. Последовательность выполнения соответствует следующей расстановке скобок:
std::cout << *(p++) << std::endl;
Если скобки расставить так:
std::cout << (*p)++ << std::endl;
то, вначале будет получен доступ к элементу массива и выведено его текущее значение, а затем произведено увеличение значения элемента массива. Перемещение указателя на следующий элемент не производится.
Указатель можно использовать в качестве переменной-счетчика в цикле for
. В этом случае начальным значением будет адрес первого элемента массива, а условием продолжения — адрес меньше адреса первого элемента плюс количество элементов. Приращение осуществляется аналогично обычному, только вместо обычной арифметики применяется адресная арифметика. Пример:
const int ARR_SIZE = 3;
int arr[ARR_SIZE] = {10, 20, 30};
for (int *p = arr, *p2 = arr + ARR_SIZE; p < p2; ++p) {
std::cout << *p << std::endl;
}
Вывести все значения с помощью цикла while
и указателя можно так:
const int ARR_SIZE = 3;
int *p = nullptr, i = ARR_SIZE, arr[ARR_SIZE] = {10, 20, 30};
p = arr;
while (i-- > 0) {
std::cout << *p++ << std::endl;
}
p = arr;
Реквизиты
ЮMoney (Yandex-деньги): 410011140483022
ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов