Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Програм. и основы алгорит.з.о..doc
Скачиваний:
5
Добавлен:
17.11.2019
Размер:
293.89 Кб
Скачать

Контрольные вопросы

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.

Операция взятия адреса & применима к величинам, имеющим имя и размещенным в оперативной памяти. Таким образом нельзя получить адрес скалярного выражения или регистровой переменной.