Направления программирования. История создания языка Си. Особенности языка, страница 16

0)  *x=1; *y=2; *z=3;

printf(“\n x=%d y=%d z=%d”,*x,*y,*z);

 x             y            z

1

 

2

 

3

 
 


1)  *z=*x;

printf(“\n x=%d y=%d z=%d”,*x,*y,*z);

x            y            z

1

 

2

 
 


2)  y=x;

printf(“\n x=%d y=%d z=%d”,*x,*y,*z);

  x            y             z

1

 

2

 

1

 
                                             free(y);

3)  *x=-1; *y=-2; *z=-3;

printf(“\n x=%d y=%d z=%d”,*x,*y,*z);

  x             y            z

-2

 
 

-3

 
 


}

Для освобождения памяти запрошенной функцией malloc используется функция: free(<имя указателя>). В нашем примере динамический объект со значением 2 стал недоступен программе, т.к. на него не указывает ни один указатель, но он продолжает занимать отведенное для него место в памяти. Если этот объект в программе не нужен, то следует освободить занимаемую им память функцией free(y).

Указатели и массивы.

Имя массива фактически является константным указателем, хранящим адрес первого элемента массива (элемента под индексом 0). Начальный адрес статического массива определяется компилятором в момент объявления массива, и такой адрес не может быть переопределен.

Пример:

1)   float data[200];

float *r= (float *)malloc(sizeof(float));

*r=1.5;

data=r;             /*содержит ошибку, т.к. значение адреса data не может быть заменено на другое значение адреса r */

2)   var a, b:array[0..9] of real;

b:=a;{ все значения из массива а перепишутся в массив b}

В Си недопустимо такое:

// массивы a  и b размещены в стеке как и другие локальные данные.

float a[10], b[10];

b=a; //ошибка, т.к. указатель на массив – константа

Разместим массив в куче.

int *a= (int *)malloc( 10*sizeof(int));                                                            a                   b

int *b= (int *)malloc( 10*sizeof(int));

 
 
b=a;  - допустимо, но два массива a и b неразличимы в памяти и изменение значений в одном из  массивов, приведет к изменению значений в другом массиве.

Для того чтобы получить два различных массива, значения из массива а могут быть переданы в массив b следующим образом:

int i;

for()i=0;i<10;i++)

b[i]=a[i];

Доступ к элементам массива не зависит от способа их описания.

Арифметические действия над указателями.

Над указателями могут быть выполнены действия целочисленной арифметики. Имеем описание : int data[100];. Адрес сотого элемента массива можно определить следующими способами:

& data[99];                   data+99;

Если а – массив или указатель, а i – целое, то следующие записи эквивалентны: a[i] , *(a+i).

Сложение (++,+n)или вычитание  указателей всегда выполняется в единицах того типа, к которому относится указатель: значение data отличается от значения data+1 на число байт, требуемое для хранения целого, т.е. 2 байта.

Указатели можно сравнивать между собой.

ptr 1==ptr2            

<=                        

!=                        

>=

<

>

Примеры использования арифметических действий над указателями.