Указатели и массивы в C++: мастерство взаимодействия
Указатели и массивы в C++
В этом руководстве мы изучим связь между массивами и указателями с практическими примерами.
В C++ указатели — это переменные, хранящие адреса других переменных. Указатель может хранить не только адрес одной переменной, но и адреса элементов массива.
Рассмотрим пример:
int *ptr;
int arr[5];
// Сохранить адрес первого элемента arr в ptr
ptr = arr;
Здесь ptr — указатель, а arr — массив int. Код ptr = arr; сохраняет адрес первого элемента массива в переменной ptr.
Обратите внимание: мы использовали arr вместо &arr[0]. Это эквивалентно, так как оба выражения дают один и тот же адрес. Следующий код идентичен приведённому выше:
int *ptr;
int arr[5];
ptr = &arr[0];
Адреса остальных элементов задаются &arr[1], &arr[2], &arr[3] и &arr[4].
Указание на каждый элемент массива
Допустим, нужно указать на четвёртый элемент массива тем же указателем ptr.
Если ptr указывает на первый элемент, то ptr + 3 будет указывать на четвёртый. Например:
int *ptr;
int arr[5];
ptr = arr;
ptr + 1 эквивалентно &arr[1];
ptr + 2 эквивалентно &arr[2];
ptr + 3 эквивалентно &arr[3];
ptr + 4 эквивалентно &arr[4];
Аналогично можно обращаться к элементам через один указатель:
// Использование оператора разыменования
*ptr == arr[0];
*(ptr + 1) эквивалентно arr[1];
*(ptr + 2) эквивалентно arr[2];
*(ptr + 3) эквивалентно arr[3];
*(ptr + 4) эквивалентно arr[4];
Если мы инициализировали ptr = &arr[2];, то:
ptr - 2 эквивалентно &arr[0];
ptr - 1 эквивалентно &arr[1];
ptr + 1 эквивалентно &arr[3];
ptr + 2 эквивалентно &arr[4];

Примечание: Адрес между ptr и ptr + 1 отличается на 4 байта, так как ptr — указатель на int (размер 4 байта в 64-битной ОС). Для char разница была бы 1 байт.
Пример 1: Указатели и массивы в C++
// C++ программа для вывода адреса каждого элемента массива
#include <iostream>
using namespace std;
int main() {
float arr[3];
// Объявление указателя
float *ptr;
cout << "Displaying address using arrays: " << endl;
// Цикл для вывода адресов всех элементов массива
for (int i = 0; i < 3; ++i) {
cout << "&arr[" << i << "] = " << &arr[i] << endl;
}
// ptr = &arr[0]
ptr = arr;
cout << "\nDisplaying address using pointers: " << endl;
// Цикл для вывода адресов с использованием указательной нотации
for (int i = 0; i < 3; ++i) {
cout << "ptr + " << i << " = " << ptr + i << endl;
}
return 0;
}
Вывод
Displaying address using arrays: &arr[0] = 0x61fef0 &arr[1] = 0x61fef4 &arr[2] = 0x61fef8 Displaying address using pointers: ptr + 0 = 0x61fef0 ptr + 1 = 0x61fef4 ptr + 2 = 0x61fef8
В программе сначала выводятся адреса элементов массива без указателя. Затем указатель ptr используется для обращения к адресам: ptr указывает на a[0], ptr + 1 — на a[1] и так далее.
В большинстве контекстов имена массивов преобразуются в указатели. Простыми словами, имя массива конвертируется в указатель. Поэтому мы можем использовать указатели для доступа к элементам массива.
Однако важно помнить: указатели и массивы — это не одно и то же.
Существуют случаи, когда имя массива не преобразуется в указатель. Подробнее: когда имя массива не распадается в указатель?
Пример 2: Использование имени массива как указателя
// C++ программа для ввода и вывода данных с использованием указательной нотации
#include <iostream>
using namespace std;
int main() {
float arr[5];
// Ввод данных с использованием указательной нотации
cout << "Enter 5 numbers: ";
for (int i = 0; i < 5; ++i) {
// Сохранение введённого числа в arr[i]
cin >> *(arr + i);
}
// Вывод данных с использованием указательной нотации
cout << "Displaying data: " << endl;
for (int i = 0; i < 5; ++i) {
// Вывод значения arr[i]
cout << *(arr + i) << endl;
}
return 0;
}
Вывод
Enter 5 numbers: 2.5 3.5 4.5 5 2 Displaying data: 2.5 3.5 4.5 5 2
Здесь:
- Мы использовали указательную нотацию для сохранения введённых пользователем чисел в массив arr:
Это эквивалентноcin >> *(arr + i);cin >> arr[i];. Отдельный указатель не объявлялся — имя массива arr само выступает в роли указателя на первый элемент. - Аналогично, для вывода значений использовался цикл
forс указательной нотацией:
Это эквивалентноcout << *(arr + i) << endl;cout << arr[i] << endl;.
Язык C
- Освоение переменных, литералов и констант в C++: подробное руководство
- Классы и объекты в C++: практическое руководство по объектно-ориентированному программированию
- Управление памятью в C++: экспертное использование new и delete
- Публичное, защищённое и приватное наследование в C++: подробный разбор
- Дружественные функции и классы в C++: мастерство контроля доступа
- Освоение указателей в C: практическое руководство от экспертов
- Понимание взаимосвязи между массивами и указателями в C
- Передача адресов и указателей в функции в C: практическое руководство
- Освоение структур и указателей в C: практическое руководство
- Структуры C++ против классов: практическое руководство для разработчиков встроенных систем