
- •1. Введение
- •2. Элементы языка
- •2.1. Первые программы
- •2.2. Алфавит языка
- •2.3. Комментарии
- •2.4. Типы данных
- •2.5. Целые типы данных
- •2.6. Плавающие типы данных
- •2.7. Константы-строки, или литералы
- •2.8. Директива препроцессора define
- •2.9. Описания
- •2.10. Модификатор const
- •3. Выражения
- •3.1. Операция и выражение присваивания
- •3.2. Арифметические операции
- •3.3. Операции отношения
- •3.4. Логические операции
- •3.5. Побитовые операции
- •3.6. Сдвиги
- •?????3.8. Тернарная или условная операция
- •3.9. Операция следования
- •3.10. Приоритеты операций и порядок вычисления
- •4.6. Оператор выбора switch
- •4.7. Оператор цикла while
- •4.8. Цикл с постусловием do-while
- •4.9. Оператор for
- •4.10. Оператор безусловного перехода
- •4.11. Оператор break
- •4.12. Оператор continue
- •4.13. Оператор return
- •5. Указатели
- •5.1. Определение указателей
- •5.2. Указатели и массивы
- •5.3. Адресная арифметика
- •5.4. Символьные массивы и строки
- •5.5. Многомерные массивы
- •5.6. Указатели и многомерные массивы
- •6. Операция sizeof
- •7. Операции для работы с динамической памятью
- •7.1. Операция выделения памяти new
- •7.2. Операция освобождения памяти delete
- •8. Функции
- •8.1. Определение и вызов функции
- •8.2. Функции. Передача аргументов
- •8.3. Передача многомерных массивов
- •8.4. Указатели на функции
- •8.5. Ссылки
- •8.6. Ссылки в качестве параметров функций
- •8.7. Аргументы по умолчанию
- •8.8. Переопределение функций
- •8.9. Шаблоны функций
- •9. Объявления и определения
- •10. Область существования имени
- •11. Область видимости
- •Здесь будет напечатано
- •12. Классы памяти
- •13. Объявления объектов и типов
- •14. Имена типов
- •15. Синоним имени типа
- •16. Правила преобразования стандартных типов
- •16.1. Явные преобразования
- •16.2. Неявные преобразования стандартных базовых типов
- •16.3. Преобразование производных стандартных типов
- •17. Перечисления
- •18. Классы
- •18.1. Объявление классов
- •18.2. Конструкторы
- •18.3. Деструкторы
- •18.4. Статические члены класса
- •18.5. Указатель this
- •18.6. Статические функции-члены
- •18.7. Указатели на члены класса
- •18.8. Инициализация данных–членов класса
- •18.9. Конструктор копирования и операция присваивания
- •18.10. Дружественные функции
- •18.11. Конструктор и операция new
- •18.12. Вызов деструктора
- •19. Производные классы
- •19.1. Построение производного класса
- •19.2. Защищенные члены класса
- •19.3. Управление уровнем доступа к членам класса
- •19.4. Последовательность вызова конструктора и деструктора при построении производного класса на основе одного базового
- •19.5. Преобразования типов
- •20. Полиморфизм
- •20.1. Раннее и позднее связывание
- •20.2. Виртуальные функции
- •20.3. Абстрактные классы
- •21. Переопределение стандартных операций
- •21.1. Основные определения и свойства
- •21.2. Операции new и delete при работе с абстрактными типами
- •21.3. Использование new при создании динамического объекта абстрактного типа
- •21.4. Операция delete
- •21.5. Преобразование типов
- •22. Некоторые особенности переопределенных операций
- •22.2. Операция [ ]
- •23. Классы и шаблоны
- •24. Списки
- •24.1. Операции над односвязными списками
- •24.2. Двунаправленные и кольцевые списки
- •24.3. Операции над кольцевыми списками
- •25. Стеки
- •25.1. Реализация стека через массив
- •25.2. Реализация стека через динамическую цепочку звеньев
- •26. Двоичные деревья
- •26.1. Определение и построение
- •26.2.Таблицы
- •27. Список литературы
5.2. Указатели и массивы
Массив - это совокупность элементов одного типа, которые расположены в памяти ЭВМ подряд, один за другим.
Признаком объявления массива являются квадратные скобки. Объявить массив из 10 элементов типа float можно так:
float a[10];
Чтобы обратиться к элементу этого массива, нужно применить операцию индексирования a[ind]. Внутри квадратных скобок помещается целое выражение, которое называется индексом. Нумерация элементов массива начинается с 0 и поэтому вышеприведенное описание говорит о том, что в памяти ЭВМ зарезервировано место под 10 переменных типа float и эти переменные есть a[0], a[1], . . . , a[9].
Приведем пример с использованием массива.
Напишем программу подсчета числа появлений каждой цифры, пробельных символов и всех остальных символов.
Число пробельных символов будем хранить в nwhite, прочих символов - в nother, а число появлений каждой из цифр - в массиве ndigit:
# include <iostream.h>
void main( ) {
int c, i, nwhite = 0, nother = 0;
int ndigit [10];
for ( i=0; i<10; i++) ndigit[i]=0;
while ( ( c=cin.get( ) )!=EOF)
if(c>=‘0’ && c<=‘9’) ++ ndigit[c – ’0’];
else if (c = = ‘ ‘|| c = = ‘\n‘ || c = = ‘\t‘) ++ nwhite;
else ++ nother;
cout<<“ цифра \n”;
for( i=0; i<10; i ++)
cout<<i<<“ вошла”<<ndigit[i]<<“ раз \n”;
cout<<“ пробельных символов - “<< nwhite <<“ прочих символов – ”
<< nother <<“\n”; }
При объявлении массива его можно инициализировать:
int c[ ] = { 1, 2, 7, 0, 3, 5, 5 };
char array[ ] = { ’h’, ’e’, ’l’, ’l’, ’o’, ’\n’, ’\0’};
Последнюю инициализацию разрешается выполнять проще:
char array[ ] = “hello\n”;
Такой синтаксис инициализации разрешен только для строк. Компилятор сам вычислит необходимый размер памяти с учетом автоматически добавляемого в конец строки символа ’\0’ с кодом 0, который является признаком завершения строки.
В языке С++ имя массива является константным указателем на первый элемент этого массива:
int mas[20];
int pmas;
pmas = &mas[0];
Последний оператор можно записать и так: pmas = mas;
Операция индексирования массива [ ] имеет 2 операнда - имя массива, т.е. указатель, и индекс, т.е. целое: a[i]. В языке С++ любое выражение указатель[индекс] по определению трактуется как
(указатель + индекс)
и автоматически преобразуется к такому виду компилятором.
Таким образом, a[3] эквивалентно (a + 3). Более того, это можно записать даже так 3[a], т.к. это все равно будет проинтерпретировано как (3+a). Здесь складываются указатель a и целое 3. В связи с этим рассмотрим так называемую адресную арифметику.
5.3. Адресная арифметика
Указатель можно складывать с целым.
Если к указателю pa прибавляется целое приращение i, то приращение масштабируется размером памяти, занимаемой объектом, на который указывает указатель pa.
Таким образом, pa+i - это адрес i-го элемента после pa, причем считается, что размер всех этих i элементов равен размеру объекта, на который указывает pa.
Итак, если a - массив, то
a+i - адрес i-го элемента этого массива, т.е.
&a[i] равен a+i и a[i] равняется (a+i).
float b[10];
float pb=b;
pb++; // Это эквивалентно pb=pb_1.
// Здесь указатель pb будет указывать
// на элемент массива b[1].
pb+=3; // Здесь pb указывает на элемент массива b[4].
Отметим, что нельзя написать b++ или b = b+i, т.к. имя массива b - это константный указатель и его изменять нельзя.
Указатели можно сравнивать.
Если p и q указывают на элементы одного и того же массива, то такие отношения, как < >= и т.д. работают надлежащим образом. Например,
p < q
истинно, т.е. = = 1, если p указывает на более ранний элемент массива, чем q. Любой указатель можно сравнить на равенство или неравенство с так называемым нулевым указателем NULL, который ни на что не указывает. Однако не рекомендуется сравнивать указатели, указывающие на различные массивы.
Указатели можно вычитать.
Если p и q указывают на элементы одного и того же массива, то p – q дает количество элементов массива между p и q.