- •Информатика основы
- •Предисловие
- •Введение
- •Программы
- •1.1. Элементы языка
- •Список основных ключевых слов
- •Типы числовых данных
- •Разделители
- •Основные бинарные операции
- •Математические функции
- •1.2. Структура программы
- •1.3. Выполнение программы
- •Контрольные вопросы
- •2.1. Загрузка и настройка системы программирования
- •2.2. Создание и работа с проектом
- •Условные графические обозначения основных блоков схем алгоритмов
- •Словесно-формульный алгоритм
- •Листинг 2.1. Lin_prog.Cpp
- •Результат выполнения программы
- •3.2. Логический тип данных и базовые логические операции
- •Операции сравнения
- •Логические операции
- •При решении задач с множеством логических условий программа существенно упрощается, если эти условия удается объединить с помощью операций и, или, не в более крупные выражения.
- •Словесно-формульный алгоритм
- •Результат выполнения программы
- •Результат выполнения программы
- •Упражнения
- •Варианты заданий
- •Области определения функции z (X,y)
- •Контрольные вопросы
- •4. Организация циклов
- •4.1. Организация программ с циклами
- •For (инициализация; условие; модификация) операторы
- •4.2. Инкремент, декремент и составные операции
- •Составные операции присваивания
- •Результат выполнения программы
- •Результат выполнения программы
- •Упражнения
- •Варианты заданий
- •Контрольные вопросы
- •5.Составление программ с массивами
- •5.1. Организация программ с массивами
- •Тип имя_массива [n];
- •Имя_массива [индекс]
- •Тип имя_массива [размер_1] [размер_2]
- •5.2. Манипуляторы и форматирование ввода-вывода
- •Манипуляторы
- •Результат выполнения программы
- •Результат выполнения программы
- •Контрольные вопросы
- •Дайте определение массива.
- •6. Составление программ с использованием функций
- •6.1. Описание, объявление и вызов функций
- •Механизм возврата из функции реализуется оператором
- •Тип имя_функции (тип размерность, тип имя_массива[ ]) ,
- •6.2. Глобальные и локальные переменные
- •Результат выполнения программы
- •6.3. Перегруженные функции
- •Результат выполнения программы
- •Упражнения
- •Варианты заданий
- •Контрольные вопросы
- •7. Программирование с использованием указателей
- •7.1. Общие сведения об указателях
- •7.2. Динамические массивы
- •Результат выполнения программы
- •Результат выполнения программы
- •7.3. Указатели и функции
- •Результат выполнения программы
- •Упражнения
- •Варианты заданий
- •Контрольные вопросы
- •8. Программирование с использованием структур
- •8.1. Определение структур
- •8.2. Организация программ с использованием структур
- •Имя_структуры . Имя_элемента_структуры
- •Список товаров
- •Результат выполнения программы
- •Упражнения
- •Варианты заданий
- •Контрольные вопросы
- •Библиографический список
- •Основные бинарные операции
- •Операции сравнения
- •Составные операции присваивания
- •Логические операции
- •Типы числовых данных
- •Константы, используемые в математических выражениях
- •Математические функции
- •Типовые сообщения об ошибках
- •Оглавление
7. Программирование с использованием указателей
Указатель– это именованная переменная, представляющая собой символический адрес, по которому располагается объект определенного типа. С помощью этой переменной организуется косвенный способ адресации.
На практике указатели чаще всего используются при работе с динамической памятью. Это свободная память, в которой можно выделять во время работы программы место для временных (промежуточных) массивов данных переменной размерности. Участки выделенной динамической памяти называютдинамическими переменнымии обращаются к ним через указатели.
7.1. Общие сведения об указателях
Объявление указателя имеет следующий вид:
type *ptr;
где ptr – указатель на значение типаtype;
* - символ унарной операции косвенной адресации.
Например:
int*z; //z– указатель на целое число типаint
float*a; //а – указатель на вещественное число типаfloat
void*p; //p– указатель на типvoid(бестиповый указатель)
Указатель инициализируется либо непосредственно при объявлении (для надежности), либо после объявления с помощью оператора присваивания. При этом ему присваивается конкретный или нулевой адрес.
Например:
intx,y=5;
int*yptr, *count=NULL; //указателю count присваивается нулевой адрес
int*xptr=&x; //указателю хptr присваивается адрес переменной х
. . . . . . . . . . .
yptr=&y; //указателю yptr присваивается адрес переменной y
Здесь &- символ унарной операции взятия адреса;NULL– символическая константа, равная нулевому адресу, по которому никогда не располагаются данные (этот адрес зарезервирован операционной системой для своих нужд).
Для того чтобы использовать значение, на которое указывает указатель, необходимо применить к указателю унарную операцию разыменования* (обращения по адресу).
Например:
x=*yptr; //присваивание числа y=5, находящегося по адресу yptr
Этот же результат можно получить, записав
x=y; //обычное присваивание без применения указателя
или
*xptr=*yptr; //по адресуxptrпомещается значение,
//расположенное по адресу yptr
Операцию * нельзя применять к бестиповому указателю, так как неизвестно какой размер памяти нужно разыменовать. Прежде чем использовать такой указатель, ему необходимо присвоить значение указателя на нужный тип данных.
Например:
float*d,c=2;void*q;
q=d; //указательqиd- синонимы указывают на типfloat
*q=c; //по адресуqпомещается значениестипаfloat
Указатель может изменять свое значение, т.е. ему можно присвоить адрес другой переменной того же типа.
Например:
yptr=&x; //yptrбудет указывать на х
Подобно другим переменным указатель имеет собственный адрес в памяти. Он может быть получен путем применения операции &к имени указателя.
Например:
cout<<&yptr; //печать адреса указателяyptr
Можно так же определить указатель на указатель и так далее сколько нужно раз.
Например:
intz=37;
int*pz=&z; //pz– указатель наz
int**ppz=&pz; //ppz– указатель на указательpz
В данном случае при вызове **ppzпоследовательно обеспечивается доступ к участку памяти *ppz= =pz, затем *pz= =z, т.е. **ppzдает значение 37.
С указателями можно выполнять не только операции присваивания и обращения по адресу, но и ряд других операций:
унарные операции ++,--;
аддитивные и составные операции с целыми числами +, -, +=, -=;
вычитание указателей (сложение указателей запрещено);
операции отношения.
Последние имеют смысл в основном при работе со структурами данных, последовательно размещенными в памяти, например с массивами. Исключение составляют операции==и !=, которые используются для любых типизированных указателей.
Массивыи указатели в С++ тесно связаны и могут быть использованы практически эквивалентно. Имя массива можно понимать какконстантный указательна первый элемент массива. Его отличие от обычного указателя в том, что его нельзя модифицировать. Однако константный указатель можно присваивать переменной типа указатель.
Например:
intb[5], *pt;
pt=b; //эта запись эквивалентнаpt=&b[0]
После инициализации указателя его можно использовать для ссылок на элементы массива b[i]с помощью записи*(pt+i).Указатели можно индексировать точно так же, как и массивы. Например, выражениеpt[i] ссылается на элемент массиваb[i].Учитывая, чтоb=&b[0], в целом можно считать, чтоb[i] – индексированный указатель. Эта взаимосвязь отражена графическина рис. 7.1.
Рис. 7.1. Взаимосвязь указателя с одномерным массивом
Двумерные массивы заданной размерности располагаются в памяти подобно одномерным массивам, занимая построчно смежные ячейки. Поэтому для работы с таким массивом достаточно одного указателя.
Например:
floatmas[4] [2], *ptr;
ptr=mas; //или ptr=& mas[0] [0]
На рис. 7.2 представлена схема расположения массива masв памяти компьютера.
Рис. 7.2. Взаимосвязь указателя и двумерного массива
Применение указателей затрудняет составление и анализ программ, поэтому их используют в тех случаях, где без них невозможно обойтись или когда они позволяют создать более оптимальный по ряду характеристик программный код.
Возможности и преимущества указателей проявляются при работе с динамическими массивами, функциями, строками и структурированными данными.