- •Московский государственный институт пищевой промышленности
- •Type * имя указателя;
- •Int **p7; //неинициализированный указатель на объект типа int * // р7 – указатель на указатель
- •1.2. Типы указателей и операции над ними
- •Операция разыменования
- •Операция преобразования типов
- •Операция присваивания
- •Операция получения адреса указателя
- •Операция сложения и вычитания
- •Операции отношений (операции сравнений)
- •1.3. Массивы Массивы и переменные с индексами
- •Int z[100]; // одномерный массив из 100 элементов типа int char s[80]; // одномерный массив из 80 элементов типа char (строка) float y[3][4];// двумерный массив из 12 элементов типа float
- •Задача – 1
- •Математическая постановка задачи
- •Задача – 2
- •Математическая постановка задачи
- •Инициализация массивов
- •Массивы и указатели
- •Динамические массивы
- •2. Функции, передача параметров
- •2.1.Определение функции
- •Void Sum(float *s,float *X, int n); //прототип функции Sum
Операция присваивания
Чтобы связать неинициализированный указатель с новым участком памяти, не занятым каким – либо объектом программы, используется оператор new или присваивается указателю явный адрес:
char * p1, *p6; int x; int *p5;
p1 = new char; // выделяется участок памяти для переменной //типа char, значение р1 присваивается // адресу этого участка
p5 = &x; // значение р5 присваивается адресу //участка памяти, выделенного для х p6 = (char *) 0xb8000000; // значение р6 присваивается адресу // видеопамяти ПЭВМ для цветного дисплея // в текстовом режиме
Обратите внимание на необходимость преобразования шестнадцатеричной константы 0xb8000000 к типу указателя наchar. Это делается с помощью операцииприведение к типу “указатель на char ” – (char *). Без этой операции операторp6 = 0xb8000000;
будет ошибочным!
Отметим также, что операция ‘&’применима только к объектам, имеющим имя и размещенным в памяти. В частности, ее нельзя применять к выражениям, неименованным константам. Кроме того, отметим, что операторnew имеется только в языке Си++ и отсутствует в Си.
Операция получения адреса указателя
Указатель, как и все другие объекты, имеет адрес выделенного для него участка памяти. Значение этого адреса доступно с помощью операции &, применяемой к указателю:
int x; int *p1 = &x; int **p2; p2 = &p1;
В этом фрагменте программы p2 – указатель на указатель на поле типаint, аp1– это указатель на поле типаint. “Адресные связи”, устанавливаемые данным фрагментом, проиллюстрированы на рис.3.

Операция сложения и вычитания
Операция вычитания применима к указателям на объекты одного типа и к указателю и целой константе. Вычитая два указателя одного типа, можно определить “расстояние” между двумя участками памяти. Это “расстояние” определяется в количестве полей, разделяющих эти участки. Этот факт иллюстрирует следующая программа:
// program - 2 #include<stdio.h>
#include<conio.h>
void main ()
{
float y1 = 1.2345, y2 = 2.3456, y3 = 3.4567;
float *p1 =&y1, *p2 = &y2 , *p3 = &y3;
clrscr();
printf (" p1 – p2 = %d \n", p1 – p2);
printf (" p1 - p3 = %d \n", p1 - p3);
printf (" *(p1 - 2) = %7.4f \n", *(p1 - 2));
printf (" *(p3 + 2) = %7.4f \n", *(p3 + 2));
getch();
}
При выполнении этой программы получим следующий результат:
p1 – p2 = 1 p1 –p3 = 2 *(p1 – 2) = 3.4567 *(p3 + 2) = 1.2345
Отсюда видно, что определенные последовательно объекты y1,y2,y3, имея типfloat, размещаются в памяти рядом, причем расстояние междуp1 иp2 равно одному полю типаfloat(4 ,байта), а междуp1 иp3 равно двум полям типаfloat (8 байт). При вычитании из указателя целочисленного значенияК, числовое значение указателя уменьшается на величину
К * sizeof (type)
где – вычитаемое,type – тип объекта, к которому отнесен указатель. В нашем примереК = 2, type имеет значениеfloat, поэтому выражениеp1 – 2 означает
уменьшение значение р1на два поля типаfloat (т. е. на 8 байт). Уменьшая же значениер1 на 8 байт мы получаем адрес поляp3, а отсюда*(p1 –2) равно3.4567.
Аналогично выполняется и операция сложения указателя с целочисленной константой. Поэтому значение *(р3 + 2)будет равно1. 2345. Суммировать же два указателя запрещено синтаксисом языка Си и Си++.
Обратите внимание на “обратный” порядок размещения объектов в памяти компьютера (в объявлениях объекты появляются в последовательности y1,y2,y3, а размещение в памяти осуществляется в последовательностиy3,y2,y1). В результате &y3 >&y2>&y1, т. е. младшие адреса размещения получают объекты, объявленные позже.
Операции инкремента (++) и декремента (--)
Декремент (автоуменьшение) указателей (--) и инкремент (автоувеличение) указателей (++) не имеют никаких новых особенностей. Как и вычитание единичной константы, операция ‘–‘ изменяет конкретное численное значения указателя типаtype * на величинуsizeof (type). Тем самым указатель “перемещается” к соседнему объекту с меньшим адресом. Аналогично выполняется операция единичного приращения ‘++’. В зависимости от положения (до операнда – указателя или после него) выполнение унарных операций ‘++’ и ‘–‘ осуществляется либо до, либо после использования значения указателя. Но это обычное свойство инкрементных и декрементных операций, которое не связано с особенностями указателей. Пример программы, использующий операцию ‘–‘ представлен ниже:
// program - 3
#include<stdio.h>
#include<conio.h>
void main ()
{
float y1 = 1.2345, y2 = 2.3456, y3 = 3.4567;
float *p;
int i;
clrscr();
for(p = &y1,i = 1;i<=3;p--,i++)
printf (" *p = %7.4f \n", *p);
getch();
}
При выполнении этой программы получим следующий результат:
*p = 1.2345 *p = 2.3456 *p =3.4567
Если в этой программе оператор цикла записать в виде:
for(p = &y3,i = 1;i<=3;p++,i++)
printf (" *p = %7.4f \n", *p);
то результат получим в обратном порядке:
*p =3.4567
*p = 2.3456
*p = 1.2345
Этот результат объясняется особенностью выделения памяти для объявляемых переменных y1,y2,y3. Эта особенность была рассмотрена выше.
