- •Содержание
- •Предисловие
- •1. Общие методические указания
- •2. Рабочая программа и методические указания к темам курса
- •2.1 Типы данных
- •2.2.1 Операторы управления
- •If (выражание) оператор_1;
- •2.2.2 Операторы ввода-вывода
- •Контрольные вопросы
- •2.3 Массивы и указатели
- •2.3.1 Указатели
- •2.3.2 Массивы
- •Контрольные вопросы
- •2.4 Типы данных, определяемые пользователем
- •2.4.1 Структуры
- •2.4.2 Перечисления
- •2.4.3 Структуры с битовыми полями
- •2.4.4 Объединение (смесь)
- •Контрольные вопросы
- •2.5 Функции
- •2.5.1 Общие сведения о функциях
- •Способы передачи параметров функции
- •2.5.2 Рекурсивные функции
- •2.5.3 Перегрузка функций
- •2.5.4 Шаблоны функций
- •Контрольные вопросы
- •3. Перечень лабораторных работ
- •Список литературы
- •Давыдов, в.Г. Программирование и основы алгоритмизации [Текст]: учеб. Пособие/ в.Г. Давыдов – м: Высшая школа, 2003. – 447с.: ил.: 22 см. – Библиогр.: с. 442. – 3000 экз. - isbn 5-060-04432-7.
Контрольные вопросы
1. Как ввести начальные значения переменных?
2. Какое месторасположение операторов описания типа в программе?
3. Какие формы представления чисел существуют в С++?
4. Какая последовательность выполнения операций в выражениях?
5. Что понимается под термином « тело цикла »?
6. Какого типа могут быть метки в операторе swith?
7. Какие существуют формы записи условного оператора? В чём их различие?
2.3 Массивы и указатели
2.3.1 Указатели
Указатели – это составной тип данных, предназначеный для хранения адресов областей памяти. В С++ различают три вида указателей, отличающиеся свойствами и набором допустимых значений:
указатели на объект;
на функцию;
на void.
Указатель не является самостоятельным типом, он всегда связан с каким-либо другим конкретным типом.
В этом параграфе мы будем рассматривать указатель на объект, содержащий адрес области памяти, в которой хранятся данные определенного типа (основного или составного).
Порядок работы с указателем:
1) Объявление указателя на объект:
тип *имя;
где тип может быть любым (кроме ссылки и битового поля), причем он может быть к этому моменту только объявлен, но еще не определен.
Звездочка относится непосредственно к имени, как признак указателя, поэтому при обращении к значению переменной она должна стоять перед именем.
Указатель может быть константой (не изменять своего значения) или переменной (изменять значение), а также указывать на константу или переменную. Указатель-константа объявляется с помощью спецификатора const и, как и любая константа, инициализируется сразу же при объявлении. Указатель-переменная тоже может быть проинициализирована при объявлении:
Пример:
int i; // целая переменая
const float pi=3.14; // вещественная константа
int *ci; //указатель на целую //переменную
const int *pci; //указатель на целую константу
int *const cp = &i; //указатель-константа на целую
//переменную
const float *const cpc = π //указатель-константа на целую константу
2) Инициализация указателя (присвоение начального значения).
Для инициализации указателя используется операция взятия адреса &.
Инициализатор записывается после имени указателя:
в круглых скобках;
после знака равенства.
Существуют следующие способы инициализации указателя:
Присвоение указателю адреса существующего объекта:
- с помощью операции взятия адреса:
int a =5; // целая переменная
int *p = &a; // в указатель записывается адрес а
int *p (&a); // инициализация другим способом
- с помощью значения другого инициализированного указателя:
int *r = p; // r и p – указатели
- с помощью имени массива, который трактуется как адрес:
int b[10]; // массив
int *t = b; // присвоение указателю адреса начала массива
присвоение указателю адреса области памяти в явном виде:
char* vp = (char *)0xb8000000; // 0xb8000000 – 16ричная
//константа (char *) – операция //приведения типа: константа //преобразуется к типу //«указатель на char»
выделение участка динамической памяти и присвоение ее адреса указателю:
с помощью операции new:
int *n = new int; // выделение памяти под значение типа // int и
// записывает адрес начала этого участка // в переменную n
int *m = new int (10) // аналогично + заполнение участка
// значением 10
с помощью функции malloc:
int *u = (int *) malloc (sizeof(int)); // аналогично int *n=new int;
3) Операции с указателями.
С указателями можно выполнять следующие операции:
разыменование (разадресация);
присваивание;
сложение с константой;
вычитание;
инкремент (++);
декремент (--);
сравнение;
приведение типов;
взятия адреса.
Операция разыменования (*). Предназначена для доступа к величине, адрес которой хранится в указателе. Ее можно использовать и для получения и для изменения величины (значения).
Конструкция *имя_указателя может считаться именем переменной, на которую ссылается указатель. С ней допустимы все действия, определенные для величин соответствующего типа. На одну и ту же область памяти может ссылаться несколько указателей различного типа. Примененная к ним операция разыменования даст разные результаты. Таким образом, если в программе имеется объявление
int a,*p; // p - указатель на int
a=1;
.........
p=&a;
то выражение
++*p; // *p=*p+1; или a=a+1; (a=2)
т.е. означает - увеличить значение переменной целого типа a на единицу.
Арифметические операции (сложение с константой, вычитание, инкремент, декремент). Автоматически учитывают размер типа величин, адресуемых указателями. Эти операции применимы только к указателям одного типа и имеют смысл в основном при работе со структурами данных, последовательно размещенными в памяти, например, с массивами.
Инкремент перемещает указатель к следующему элементу массива.
Декремент – к предыдущему.
Фактически значение указателя изменяется на величину sizeof(тип). Если указатель изменяется на какую-либо константу, то его значение изменяется на величину этой константы, умноженную на размер объекта данного типа, например
p=p+3; // p = p + 3 * 4(байта), где р – имя указателя.
В нашем примере мы увеличили значение указателя на 3*4=12 байт, т.е. «сдвинули» его вправо на три элемента типа int (размером по 4 байта каждый).
Разность двух указателей – это разность их значений, деленная на размер типа в байтах. Суммирование двух указателей не допускается.
При записи выражений с указателями следует обращать внимание на приоритет операций. Пример:
int a, *p = &a; //определение переменной а и указателя р
*p++=10; //аналогично последовательности:
// a=10;(*p=10;) p++;
(*p)++; // аналогично: a++; (a=a+1;) теперь а=11.
Операция взятия адреса & применима к величинам, имеющим имя и размещенным в оперативной памяти. Таким образом нельзя получить адрес скалярного выражения или регистровой переменной.