- •Оглавление
- •1.2. Свойства языков программирования
- •1.3. Основные парадигмы программирования Процедурное программирование
- •Модульное программирование
- •Абстракция данных
- •Объектно-ориентированное программирование
- •Непечатные символы
- •Тема 2 Типы данных
- •2.1. Понятие переменной и объявление переменных
- •Объявление переменных
- •Встроенные типы данных
- •Размер памяти, выделяемой под встроенные типы данных
- •2.2. Константы и перечисления Константные переменные
- •Перечисления
- •2.3. Операции и выражения
- •Мультипликативные операции
- •Операции сравнения
- •Побитовые логические операции
- •Побитовые операции
- •Комментарии
- •Оператор while(пока)
- •Оператор do/while(выполнять/пока)
- •Оператор for(цикл)
- •Оператор множественного выбора switch
- •Операторы breakиcontinue
- •Тема 4 Массивы
- •4.1.Определение, объявление и инициализация массивов
- •Объявления и инициализация массивов в программе
- •4.2. Сортировка массивов Пузырьковая сортировка
- •Сортировка вставками
- •4.3. Поиск в массивах Линейный поиск
- •Двоичный поиск
- •4.4. Многомерные массивы
- •Тема 5 Указатели Объявления и инициализация переменных указателей
- •5.1. Операции над указателями
- •5.2. Выражения и арифметические действия с указателями
- •5.3. Взаимосвязи между указателями и массивами
- •5.4. Массивы указателей
- •5.5. Динамическое выделение памяти под массивы
- •Тема 6 Функции
- •6.2. Определения функций
- •Генерация случайных чисел
- •6.3. Классы памяти и область действия Классы памяти
- •Область действия
- •6.4. Рекурсия
- •6.5. Ссылки и ссылочные параметры
- •Вызов функций по ссылке с аргументами указателями
- •6.6. Использование спецификатораconstс указателями
- •6.7. Перегрузка функций
- •Аргументы по умолчанию
- •6.8. Передача массивов в функции
- •6.9. Указатель на функцию
- •6.10. Командная строка аргументов
- •6.11 Неопределенное количество аргументов
- •Тема 7 Введение в обработку строк
- •7.1. Работа со строками в с
- •Понятие символов и строк в с
- •Функции для работы со строками
- •Определение длины строки
- •Сложение двух строк (конкатенация)
- •Добавление к исходной строке указанного количества символов.
- •Копирование строки в другую строку
- •Сравнение строк
- •Получение строки от пользователя
- •Тема 8 Работа с файлами
- •Открытие файла
- •Чтение из файла символа или строки символов
- •Запись символа или строки символов в файл
- •Смещение внутри файла
- •Значения параметра fromwhereфункцииfseek
- •Закрытие файла
- •Тема 9 Компоновка программ и препроцессор
- •9.1. Компоновка программ
- •Проблема использования общих функций и имен
- •Использование включаемых файлов
- •9.2. Препроцессор
- •Определение макросов
- •Условная компиляция
- •Дополнительные директивы препроцессора
- •Тема 10 Структуры
- •10.1. Определение структур и доступ к элементам
- •Доступ к элементам структур
- •Использование структур
- •10.2. Битовые поля
- •10.3. Объединения
- •10.4. Построение связных списков на основе структур с самоадресацией
- •Создание простого связного списка
- •Очереди
- •Деревья
- •Список рекомендуемой литературы
5.2. Выражения и арифметические действия с указателями
С указателями [1] может выполняться ограниченное количество арифметических операций. Указатель можно увеличивать (++), уменьшать (--), складывать с указателем целые числа (+или+=), вычитать из него целые числа (-или-=) или вычитать один указатель из другого.
Допустим, что объявлен массив int v[10]и его первый элемент находится в памяти в ячейке3000. Допустим, что указателюvPtrбыло присвоено начальное значение путем указания наv[0], т.е. начальное значениеvPtrравно3000(см. рис. 5.2).
Указателю vPtrможно было дать начальное значение указанием на массивvс помощью одного из следующих операторов:
vPtr = v;
vPtr = &v[0];
В общепринятой арифметике сложение 3000 + 2дает значение3002. Это нормально, но не в случае арифметических действий с указателями. Когда целое складывается или вычитается из указателя, указатель не просто увеличивается или уменьшается на это целое, но это целое предварительно умножается на размер объекта, на который ссылается указатель. Количество байтов зависит от типа данных. Например, оператор
vPtr +=2;
выработал бы значение 3008 (3000 + 2*4)в предположении, что целое хранится в 4 байтах памяти. В массивеvуказательvPtrтеперь указал бы наv[2]. Если целое хранится в 2 байтах памяти, то тот же самый оператор дал бы результат в памяти ячейку3004 (3000+2*2). И т.д.
Ячейка 3000
3004 3008 3012 3016
Переменная
указатель vPtr
Рис. 5.2. Указатель на массив целых чисел
Если указатель vPtrбыл увеличен до значения3016, указывающего наv[4], оператор
vPtr -= 4;
вернул бы vPtrобратно к значению3000– к началу массива. Если указатель увеличивается или уменьшается на 1, можно использовать операции инкремента (++) или декремента (--).
Переменные указатели можно вычитать друг из друга. Например, если vPtrсодержит ячейку3000,v2Ptrсодержит адрес3008, оператор
x = v2Ptr – vPtr;
присвоит хзначение разности номеров элементов массива, на которые указываютvPtrиv2Ptr, в данном случае2.
Арифметика указателей теряет смысл, если она выполняется не над массивами. Нельзя предполагать, что две переменные одинакового типа хранятся в памяти вплотную друг к другу, если они не соседствуют в массиве.
5.3. Взаимосвязи между указателями и массивами
Массивы и указатели в С++ тесно связаны и могут быть использованы почти эквивалентно. Имя массива можно понимать как указатель, постоянно ссылающийся на первый элемент массива (константный указатель). Указатели можно использовать для выполнения любой операции, включая индексирование массива.
Предположим, объявлены массив целых чисел b[5]и целая переменная-указательbPtr. Поскольку имя массива (без индекса) является указателем на первый элемент массива, то можно задать указателюbPtrадрес первого элемента массиваbс помощью оператора
bPtr = b;
это эквивалентно присваиванию адреса первого элемента массива следующим образом:
bPtr = &b[0];
Сослаться на элемент массива b[3]можно с помощью выражения указателя
*(bPtr + 3)
В приведенном выражении цифра 3являетсясмещениемуказателя. Когда указатель указывает на начало массива, смещение показывает, на какой элемент массива должна быть ссылка, так что значение смещения эквивалентно индексу массива. Предыдущую запись называют записьюуказатель-смещение. Скобки необходимы, потому что приоритет*выше, чем приоритет.+. Без скобок это выражение прибавило бы число3к значению выражения*bPtr(т.е.3было бы прибавлено кb[0]в предположении, чтоbPtrуказывает на начало массива).
Сам массив можно рассматривать как указатель и использовать в арифметике указателей.
Например, выражение
*(b + 3)
тоже ссылается на элемент массива b[3]. Вообще все выражения с индексами массива могли бы быть записаны с помощью указателей и смещений. В этом случае запись указатель-смещение применялась бы к имени массива как к указателю.
Указатели можно индексировать точно так же, как и массивы. Например, выражение
bPtr[1]
ссылается на элемент массива b[1], это выражение рассматривается как записьуказатель-индекс.
Имя массива является константнымуказателем, оно всегда указывает на начало массива. Поэтому выражение
b += 3;
не разрешено, потому что оно пытается модифицировать значение имени массива с помощью арифметической операции над указателем.