Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Archive / Метод_указ.doc
Скачиваний:
84
Добавлен:
30.03.2015
Размер:
700.42 Кб
Скачать

Лабораторная работа 6 указатели

В Си-программах широко используется переменная типа указатель, значением которой является адрес другой переменной или функции. В описании необходимо сообщить, что данная переменная есть не только указатель, но и данный указатель указывает или ссылается на переменную некоторого типа, т.е. компилятору необходимо определить, сколько байт памяти будет связано с данным указателем.

Пример.

int *rt; float *s; void *s_p;

указатель типа void («пустой») может указывать на объект любого типа.

Наиболее важными операциями, связанными с указателями, являются операция обращения по адресу * (разыменования или снятия ссылки) и операция определения адреса &. Первая операция служит для присваивания или считывания значений переменной, на которую ссылается данный указатель. Вторая операция возвращает адрес памяти своего операнда. Размер возвращаемого адреса зависит от применяемой модели динамической памяти.

Пример.

#include <stdio.h>

void main ()

{int i=10, s, *x, *f, *v=&i, *x=9,s=5,f=&s;

printf (“\n Размер x=%d”, sizeof(x));

printf (“\n Значение указателей x=%u v=%u &i=%u”, x, v, &i);

printf (“\n Значение по адресу x=%d”, *x);

printf (“\n Адрес s=%u”, &s);

}

При работе с динамическими переменными типа указатель распространенной ошибкой является то, что при описании указатель не инициализируется, что приводит к тому, что компилятор резервирует память только для хранения адреса. В примере, приведенном выше, под переменные *х и *f отводится только два байта под хранение адреса и не отводится два байта под хранение переменной типа int. Что может привести к попытке размещения в процессе выполнения программы значения переменной по начальному адресу, связанному с какой-либо частью операционной системы.

При работе с переменными типа указатель следует придерживаться следующего алгоритма:

1. Предварительно инициализировать указатель, т.е. присвоить указателю адрес предварительно инициализированной переменной, как это выполнено в примере для указателя *v.

2. Использовать функции распределения динамической памяти – «кучи», описанные в библиотечном файле alloc.h:

  • void *malloc(unsigned s) – выделение памяти размером s байт;

  • void *calloc (unsigned nel, unsigned els) – выделение памяти для nel элементов, для которых размер каждого элемента определяется переменной els,

  • void *realloc(void *blok, unsigned s) – изменение размера ранее выделенной памяти для блока *block до величины s байт;

  • void far *farcalloc(unsigned long nel, unsigned long els) – выделение памяти для дальней ее модели из nel элементов, где размер каждого элемента els;

  • void free (void *blok) – освобождение ранее выделенной памяти.

Все функции имеют тип void, поэтому они совместимы с указателями любого типа и справедлива запись x=(int*)malloc(sizeof(int)), т.е. адрес, выдаваемой функцией malloc, связывается с типом int. Данные функции гарантируют, что переменной-указателю не присваивается адрес, используемой системой.

Пример. Вычислить сумму n элементов массива вещественного типа.

# include <stdio.h>

# include <alloc.h>

void main()

{float *a, s=0, *prn, f;

int i, n;

printf (“Введите размер массива а \n”);

scanf(“%d”,&n);

a=(float *)malloc(n*sizeof(float));

if (a==0) {printf (“No memory”); exit (1);}

else {ptr=a; printf(“Input array a \n”);

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

{scanf(“%f”, ptr); f=*ptr; s+=f; ptr++;}

printf (“s=%e\n”, s);

}

free(a);

}