Основы информатикиОсновы информатики
Массивы. Указатели.Массивы. Указатели.
Заикин Олег Сергеевич
http://sat.isa.ru/pdsat/files/teaching/[email protected]
Массив – набор элементов
•одинакового типа
•расположенных в памяти подряд (друг за другом)
•обращение происходит с применением общего имени
•обращение к конкретному элементу осуществляется по индексу
Массив является структурой с произвольным доступом (в отличие от списка).
МассивМассив
Динамическим называется массив, размер которого может меняться во время исполнения программы.
Динамические массивы делают работу с данными более гибкой, так как не требуют предварительного определения хранимых объемов данных, а позволяют регулировать размер массива в соответствии с реальными потребностями.
Статическими называют массивы, размер которых в программе определен и не может меняться.
Динамика и статикаДинамика и статика
Массивы с одним индексом называют одномерными, с двумя — двумерными и т. д.
Одномерный массив соответствует вектору, двумерный — матрице.
Чаще всего применяются массивы с одним или двумя индексами, реже — с тремя, ещё большее количество индексов встречается крайне редко.
Размерность массиваРазмерность массива
Объявление одномерного статического массива
тип имя_массива[размер-константа];
int A[4]; // одномерный статический массив целых чисел длины 4
// нумерация элементов от 0 до 3
МассивМассив
Номер элемента 0-й 1-й 2-й 3-й …
Имя элемента A[0] A[1] A[2] A[3] …
Адрес элемента 0108 010a 010c 010e …
Объявление двумерного статического массива
тип имя_массива[размер1][размер2];
float B[12][15]; // двумерный статический массив вещественных
// чисел размера 12 на 15
// нумерация по строкам от 0 до 11, по столбцам от 0 до 14
МассивМассив
Доступ к элементу – с помощью []
Пример
int A[10];
for (int i=0; i < 10; i++)
A[i] = i*i; // присваивание элементу массива
for (int i=0; i < 10; i++)
cout << A[i] << ’ ’; // вывод элементов массива
Вывод: 0 1 4 9 16 25 …81
МассивМассив
Одномерный массив одномерных массивов.
Объявление
Тип имя_массива[размер1][размер2];
int B[3][10]; // матрица с 3 строками и 10 столбцами
B[2, 5] – неправильное обращение
B[2][5] – правильное обращение
char имя_массива[размер1][размер2] – массив строк
Двумерный массивДвумерный массив
Формат
тип имя_массива[размер] = {список_значений}
значения в списке разделены запятыми
int A[4] = {1, 2, 3, 4};
Для символьных массивов
тип имя_массива[размер] = “строка”
char str[7] = “Привет”;
const char str[7] = “Привет”; // строка-константа
Инициализация Инициализация статических массивовстатических массивов
Формат
тип имя_массива[размер1] [размер2] = {список_значений}
в списке значения разделены запятыми
int A[3][2] = {1,4, 2,4, 5, 8};
ИнициализацияИнициализация статического двумерного статического двумерного массивамассива
Способ 1. Низкоуровневый (наследство от языка C) – через указатели
Способ 2. Высокоуровневый, через vector (из библиотеки STL)
Динамические массивы Динамические массивы в в C++C++
Указатель – переменная, которая хранит адрес другой переменной (адрес памяти).
Указатель (англ. pointer) — переменная, диапазон значений которой состоит из адресов ячеек памяти или специального значения — нулевого адреса. Последнее используется для указания того, что в данный момент там ничего не записано.
Аналогия с указателями у дороги – они содержат информацию о там, как и за какое время добраться до нужного места.
УказателиУказатели
Две основные операции над указателями: присваивание и разыменование.
Первая из этих операций присваивает указателю некоторый адрес. Вторая служит для обращения к значению в памяти, на которое указывает указатель.
Нулевой указатель − это указатель, хранящий специальное значение, используемое для того, чтобы показать, что данная переменная-указатель не ссылается (не указывает) ни на какой объектВ языках Си и C++ это 0 или макрос NULL.
УказателиУказатели
Использование символа * перед именем переменной в объявлении превращает ее в указатель.
Формат
тип *имя_переменной;
Пример
int *a; // указатель на переменную целочисленного типа
УказателиУказатели
Унарный оператор & возвращает адрес памяти, по которому расположен операнд.
// balptr получает адрес переменной balance
int *balptr;
int balance = 3200;
balptr = &balance;
Унарный оператор * (разыменование) возвращает значение переменной, расположенной по адресу, на который указывает операнд.
// переменной value присваивается значение
// переменной balance
int value = *balptr;
УказателиУказатели
УказателиУказателиПеременная num объявляется и инициализируется. После чего объявляется переменная-указатель pNum. Затем указателю pNum присваивается адрес переменной num. Таким образом обе переменные можно использовать для доступа к одному и тому же месту в памяти.
balance = 3200;
balptr = &balance;
value = *balptr;
УказателиУказатели
С помощью указателей можно присваивать значения.
*p = 101; // переменной, на которую указывает p,
// присваивается значение 101
(*p)++; // инкремент значения переменной, на которую
// указывает p
int *p, num;
p = #
*p = 100; // значение num равно 100
(*p)++; // значение num равно 101
Арифметика указателейАрифметика указателей
Операции: ++, --, + и –
Пример.
p – указатель на int переменную с адресом 2000.
После выполнения p++ p указывает на адрес 2004 (следующее int значение).
Указатели можно сравнивать, используя операторы отношения ==, < и >. Смысл имеет сравнение указателей на разные элементы одного и того же массива.
Арифметика указателейАрифметика указателей
Указатель можно рассматривать как динамический массив.
С помощью операторов new/delete можно выделять/освобождать память для динамического массива.
Указатель ссылается на первый элемент массива (имя массива без индекса образует указатель на начало этого массива).
Эквивалентно: ptr[4] и *(ptr+4)
Позволяет обращаться к элементам массива по индексу.
Динамический массивДинамический массив
ОператорыОператоры выделения и выделения и освобождения памятиосвобождения памятиnew тип[размер]
возвращает адрес непрерывного участка памяти для объекта типа тип размерностью размер
delete[] имя_указателя
освобождает память, выделенную оператором new, начиная с адреса, на который ссылается указатель.
Пример.
int ar_sz=10;
float *ptr = new float[ar_sz]; // выделили область памяти
ptr[1]=1; ptr[2]=2;
delete[] ptr; // осовободили память
Указатели могут храниться в массивах.
Объявление 5-элементного массива указателей на int.
Фактически - двумерный массив с размерами: 1 2 3 4 5
Массивы указателейМассивы указателей
const int arr_size = 5;void main() {
int *arr[arr_size];for (int i = 0; i < arr_size; i++) {
arr[i] = new int[i+1];for (int j = 0; j < i + 1; j++) {
arr[i][j] = j + 1;cout << arr[i][j] << " ";
}cout << endl;
}}
Вывод:11 21 2 31 2 3 41 2 3 4 5
Массивы указателейМассивы указателейДинамический двумерный массив.Выделение и освобождение памяти.
int **arr;arr = new int*[3];for(int i = 0; i < 3; i++)
arr[i] = new int[2];
// освобождать память нужно такfor(int i = 0; i < 3; i++)
delete[] arr[i];delete[] arr;
Утечки памятиУтечки памятиЕсли не освобождать память, то может остаться «мусор» - фактически занятые на время выполнения программы участки памяти, к которым из программы нельзя обратиться.
int *arr;arr = new int[5];arr = new int[6]; // утечка памяти
Выделенная память должна освобождаться.Каждому new должен соответствовать delete.