пятница, 5 февраля 2016 г.

XV занятие "Знакомство с указателями"

На пятнадцатом занятии мы познакомились с указателями в C/C++ - узнали, что такое указатели, как объявить указатель и выделить память для него, для чего нужны указатели и как с ними работать.


Краткое содержание занятия:

1. Указатели в C/C++ - это мощнейший инструмент работы с памятью. Используя указатели можно работать с памятью динамически, т.е. выделять именно столько памяти, сколько Вам понадобится во время выполнения программы. Этот размер памяти заранее может быть неизвестен. Например, в C/C++ невозможно написать нечто подобное:

int l;
scanf("%i",&l);
int mas[l];

Возникнет ошибка "error C2057: требуется константное выражение". Это значит, что размер массива должен быть однозначно определен на этапе компиляции (а не на этапе исполнения). Поэтому мы могли объявить массив только используя константу:

int const l=10;
int mas[l];

Таким образом, мы видим, что, массив может быть только фиксированной длины. Другими словами, мы не можем ввести размер массива с клавиатуры. Это ограничение связано с тем, что все переменные (в том числе и массивы) располагаются в т.н. статической памяти, но его легко можно обойти, используя указатели и динамическую память.

Указатель (pointer) - это переменная, хранящая адрес другой переменной. Можно провести аналогию указателя в 

C/C++ с ярлыком в ОС Windows. Ярлык указывает (хранит адрес) на файл, а указатель указывает (хранит адрес) на переменную. Указатель также может указывать и на структуру, функцию, объект, файл и т.д.; устройства также имеют адрес. Указатель представляет собой адрес (шестнадцатиричное число) первого байта информации, размещенной в памяти.


2.Объявление и использование указателей
Указатель объявляется следующим образом:
int *a;

После объявления указателя, необходимо выделить память для хранения данных, на которые будет указывать этот указатель. Это можно сделать несколькими способами:
a = (int*)malloc(1*sizeof(int));
a = (int*)calloc(1,sizeof(int)); //инициализирует нулями
int *a = new int(1);  // из c++

Память при помощи функций malloc и calloc выделяется в байтах. В этих записях число '1' означает количество блоков памяти, а функция sizeof(int) возвращает длину одного блока, равную тому количеству байт, которое занимает тип int.

После работы с указателями необходимо освободить занимаемую данными память:
free(a);  // для malloc и calloc
delete a; // для new в C++

Работать с указателями можно как и с обычными переменными, например, чтобы к переменной типа int, на которую указывает указатель *a прибавить число 29 и записать результат в переменную b, необходимо записать:
b = *a + 29;

3. Связь указателей и массивов

Работая с указателями, можно выделить память не для одного блока данных (одной переменной), а для многих (подобие массива). Для этого необходимо заменить число '1' при выделении памяти на желаемое количество, например:
a = (int*)malloc(5*sizeof(int)); //вместо '5' можно
a = (int*)calloc(5,sizeof(int)); //использовать переменную

int *a = new int(5);

Освобождение памяти при этом не изменится:
free(a);  // для malloc и calloc
delete a; // для new в C++

А вот работа с указателями станет похожей на работу с массивами:
*a - это адрес первого блока данных (первый элемент массива, *a+0 или a[0])
*a+1это адрес второго блока данных (второй элемент массива a[1])
*a+2это адрес третьего блока данных (третий элемент массива a[2]) и т. д.
Теперь стало понятно, почему массивы в C/C++ нумеруются не с 1, а с 0! Записи *a+12 и a[12] абсолютно идентичны и воспринимаются компилятором одинаково.

4. Листинг программы ptr:

















Скачать листинг программы (в текстовом формате)

Комментариев нет:

Отправить комментарий