ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 23.06.2021
Просмотров: 1685
Скачиваний: 3

41
int *u=(int*)malloc(sizeof(int)); // в функцию передается количество требуемой
памяти в байтах, т. к. функция возвращает значение типа void*, то его необходимо
преобразовать к типу указателя (int*).
free(u); //освобождение выделенной памяти
7.3. Операции с указателями
С указателями можно выполнять следующие операции:
1)
разыменование (*);
2)
присваивание;
3)
арифметические
операции
(сложение
с
константой,
вычитание,
инкремент ++, декремент --);
4)
сравнение;
5)
приведение типов.
1) Операция разыменования предназначена для получения значения переменной или
константы, адрес которой хранится в указателе. Если указатель указывает на
переменную, то это значение можно изменять, также используя операцию
разыменования.
Примеры:
int a; //переменная типа int
int*pa=new int; //указатель и выделение памяти под динамическую переменную
*pa=10;//присвоили значение динамической переменной, на которую указывает
указатель
a=*pa;//присвоили значение переменной а
Присваивать значение указателям-константам запрещено.
2) Приведение типов
На одну и ту же область памяти могут ссылаться указатели разного типа. Если
применить к ним операцию разыменования, то получатся разные результаты.
int a=123;
int*pi=&a;
char*pc=(char*)&a;
float *pf=(float*)&a;
printf("\n%x\t%i",pi,*pi);
printf("\n%x\t%c",pc,*pc);
printf("\n%x\t%f",pf,*pf);
При выполнении этой программы получатся следующие результаты:
66fd9c 123
66fd9c {
66fd9c 0.000000
Т. е. адрес у трех указателей один и тот же, но при разыменовании получаются
разные значения в зависимости от типа указателя.
В примере при инициализации указателя была использована операция
приведения типов. При использовании в выражении указателей разных типов, явное
преобразование требуется для всех типов, кроме void*. Указатель может неявно
преобразовываться в значения типа bool, при этом ненулевой указатель преобразуется в
true, а нулевой в false.
3) Арифметические операции применимы только к указателям одного типа.
-
Инкремент увеличивает значение указателя на величину sizeof(тип).
Например:
char *pc;
int *pi;

42
float *pf;
. . . . .
pc++;//значение увеличится на 1
pi++;//значение увеличится на 4
pf++;//значение увеличится на 4
-
Декремент уменьшает значение указателя на величину sizeof(тип).
-
Разность двух указателей – это разность их значений, деленная на размер
типа в байтах.
Например:
int a=123,b=456,c=789;
int*pi1=&a;
int *pi2=&b;
int*pi3=&c;
printf("\n%x",pi1-pi2);
printf("\n%x",pi1-pi3);
Результат
1
2
Суммирование двух указателей не допускается.
Можно суммировать указатель и константу:
pi3=pi3+2;
pi2=pi2+1;
printf("\n%x\t%d",pi1,*pi1);
printf("\n%x\t%d",pi2,*pi2);
printf("\n%x\t%d",pi3,*pi3);
Результат выполнения программы:
66fd9c 123
66fd9c 123
66fd9c 123
При записи выражений с указателями требуется обращать внимание на
приоритеты операций.

43
8. Ссылки
8.1. Понятие ссылки
Ссылка – это синоним имени объекта, указанного при инициализации ссылки.
Формат объявления ссылки
тип & имя =имя_объекта;
Примеры:
int x;// определение переменной
int& sx=x;// определение ссылки на переменную х
const char& CR=’\n’;//определение ссылки на константу
8.1. Правила работы со ссылками:
1)
Переменная ссылка должна явно инициализироваться при ее описании, если она
не является параметром функции, не описана как extern или не ссылается на поле
класса.
2)
После инициализации ссылке не может быть присвоено другое значение.
3)
Не существует указателей на ссылки, массивов ссылок и ссылок на ссылки.
4)
Операция над ссылкой приводит к изменению величины на которую она
ссылается
Ссылка не занимает дополнительного пространства в памяти, она является
просто другим именем объекта.
Пример1:
#include <iostream.h>
void main()
{
int I=123;
int &si=I;
cout<<”\ni=”<<I<<” si=”<<si;
I=456;
cout<<”\ni=”<<I<<” si=”<<si;
I=0; cout<<”\ni=”<<I<<” si=”<<si;
}
Выведется
I=123 si=123
I=456 si=456
I=0 si=0

44
9. Указатели и массивы
9.1. Одномерные массивы и указатели
При определении массива ему выделяется память. После этого имя массива
воспринимается как константный указатель того типа, к которому относятся элементы
массива. Исключением является использовании операции sizeof (имя_массива) и
операции &имя_массива.
Примеры:
int a[100];
int k=sizeof(a);// результатом будет 4*100=400 (байтов).
int n=sizeof(a)/sizeof(a[0]);//количество элементов массива
Результатом операции & является адрес нулевого элемента массива:
имя_массива==&имя_массива=&имя_массива[0]
Имя массива является указателем-константой, значением которой служит адрес
первого элемента массива, следовательно, к нему применимы все правила адресной
арифметики, связанной с указателями. Запись имя_массива[индекс] это выражение с
двумя операндами: имя массива и индекс. Имя_массива - это указатель константа, а
индекс определяет смещение от начала массива. Используя указатели, обращение по
индексу можно записать следующим образом: *(имя_массива+индекс).
Пример:
for(int i=0;i<n;i++)//печать массива
cout<<*(a+i)<<" ";//к имени адресу массива добавляется константа i и
полученное //значение разыменовывается
Так как имя массива является константным указателем, то его невозможно
изменить, следовательно, запись *(а++) будет ошибочной, а *(а+1) - нет.
Указатели можно использовать и при определении массивов:
int a[100]={1,2,3,4,5,6,7,8,9,10};
int * na=a;//поставили указатель на уже определенный массив
int b=new int[100];//выделили в динамической памяти место под массив из 100
элементов
9.2. Многомерные массивы и указатели
Многомерный массив это массив, элементами которого служат массивы.
Например, массив с описанием int a[4][5] – это массив из 4 указателей типа int*,
которые содержат адреса одномерных массивов из 5 целых элементов (см. рис.).
int **a
Рис.
Инициализация многомерных массивов выполняется аналогично одномерным
массивам. Примеры:
int a[3][4] =
{{11,22,33,44},{55,66,77,88},{99,110,120,130}};//проинициализированы все //элементы
массива
Элементы
типа *int
*(a+1) – адрес строки массива с номером 1
0
1
2
3
0 1 2 3 4
0
1
2 3 4
0 1 2 3 4
0 1 2 3 4

45
int b[3][4] = {{1},{2},{3}};//проинициализированы первые элементы каждой
строки
int c[3][2]={1,2,3,4,5,6};//проинициализированы все элементы массива
Доступ к элементам многомерных массивов возможен и с помощью
индексированных переменных и с помощью указателей:
a[1][1] – доступ с помощью индексированных переменных,
*(*(a+1)+1) – доступ к этому же элементу с помощью указателей (см. рис.).
9.3. Динамические массивы
Операция new при использовании с массивами имеет следующий формат:
new тип_массива
Такая операция выделяет для размещения массива участок динамической памяти
соответствующего размера, но не позволяет инициализировать элементы массива.
Операция new возвращает указатель, значением которого служит адрес первого
элемента массива. При выделении динамической памяти размеры массива должны
быть полностью определены.
Примеры:
1. int *a=new int[100];//выделение динамической памяти размером 100*sizeof(int)
байтов double *b=new double[10];// выделение динамической памяти размером
10*sizeof(double) байтов
2. long(*la)[4];//указатель на массив из 4 элементов типа long
lа=new[2][4];//выделение динамической памяти размером 2*4*sizeof(long)
байтов
3. int**matr=(int**)new int[5][10];//еще один способ выделения памяти под
двумерный //массив
4. int **matr;
matr=new int*[4];//выделяем память под массив указателей int* их n
элементов
for(int I=0;I<4;I++)matr[I]=new int[6];//выделяем память под строки массива
Указатель на динамический массив затем используется при освобождении
памяти с помощью операции delete.
Примеры:
delete[] a;//освобождает память, выделенную под массив, если а адресует его
начало
delete[]b;
delete[] la;
for(I=0;I<4;I++)delete [] matr[I];//удаляем строки
delete [] matr;//удаляем массив указателей
Пример
Удалить из матрицы строку с номером K
#include <iostream.h>
#include <string.h>
#include <iostream.h>
#include <stdlib.h>
void main()
{
int n,m;//размерность матрицы
int i,j;