ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 23.06.2021

Просмотров: 1685

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

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; 


background image

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); 
Результат  


Суммирование двух указателей не допускается. 
Можно суммировать указатель и константу: 
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 
При  записи  выражений  с  указателями  требуется  обращать  внимание  на 

приоритеты операций. 


background image

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 


background image

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  4   

 0  

1

   2  3  4   

 0  1   2  3  4   

 0  1   2  3  4   


background image

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;