Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ekzamen_Informatika_otvety.doc
Скачиваний:
53
Добавлен:
11.05.2015
Размер:
443.39 Кб
Скачать

27.Указатели. Связь между указателями и массивами.

Указатель – это переменная, которая может содержать адрес некоторого объекта. Указатель объявляется следующим образом:

<тип> *< ID переменной-указателя>;

Например: int *a; double *f; char *w;

С указателями связаны две унарные операции & и *. Операция & означает «взять адрес» операнда. Операция * имеет смысл - «значение, расположенное по указанному адресу». Обращение к объектам любого типа как операндам операций в языке C может проводиться:

- по имени (идентификатору - ID);

- по указателю (операция косвенной адресации):

указатель = &ID_объекта;

Пример 1:

43

int x, // переменная типа int

*y; // указатель на элемент данных типа int

y=&x; // y - адрес переменной x

*y=1; // косвенная адресация указателем поля x, т.е.

// по указанному адресу записать 1  x=1;

Пример 2:

int i, j=8,k=5, *y;

y=&i;

*y=2; // i=2

y=&j;

*y+=i; // j+=i  j=j+i  j=j+2=10

y=&k;

k+=*y; // k+=k  k=k+k = 10

(*y)++; // k++  k=k+1 = 10+1 = 11

При вычислении адресов объектов следует учитывать, что идентификаторы массивов и функций являются константными указателями. Такую константу можно присвоить переменной типа указатель, но нельзя подвергать пре-образованиям, например:

int x[100], *y;

y = x; // Правильно - присваивание константы переменной

x = y; // Ошибка: в левой части - указатель-константа

Указателю-переменной можно присвоить значение другого указателя, либо выражения типа указатель с использованием, при необходимости, операции приведения типа. Приведение типа необязательно, если один из указателей

имеет тип "void *".

int i,*x;

char *y;

x=&i; // x  поле объекта int

y=(char *)x; // y  поле объекта char

y=(char *)&i; // y  поле объекта char

Значение указателя можно вывести на экран с помощью спецификации %p (pointer), результат выводится в шестнадцатеричном виде. Рассмотрим фрагмент программы:

int a=5, *p, *p1, *p2;

p=&a; p2=p1=p;

++p1;p2+=2;

printf(“a=%d, p=%d, p=%p, p1=%p, p2=%p.\n”, a, p, p, p1, p2);

Результат выполнения: a=5, *p=5, p=FFC8, p1=FFCC, p2=FFD0.

Графически это выглядит так (адреса взяты символически):

4001 4003 4005 4007 4009

4000

p

4002

p1

4004

p2

4006 4008 400A

p=4000, p1=4002=(4000+1*sizeof(*p)) -> 4000+2 (int)

р2=4004=(4000+2*sizeof(*p)) -> 4000+2*2

Связь между указателями и массивами:

Идентификатор массива указывает адрес памяти, начиная с которого он расположен, т.е. адрес его первого элемента. Работа с массивами тесно связана с применением указателей.

Пусть объявлен массив aиз 5 целочисленных элементов:

inta[5];

a

a[0]

a[1]

a[2]

a[3]

a[4]

4000 4004 4008 4012 4016

Здесь приведено символическое изображение оперативной памяти, выделенной компилятором для объявленного целочисленного массива а[5]. Адрес массива выбирается компилятором в зависимости от размера доступной памяти, наличия других переменных и массивов и др. Для конкретности, здесь положено значение адреса, равное 4000. В реальной программе вместо 4000 может быть другое значение, но относительное положение элементов массива всегда остается постоянным.

В языке С идентифи­каторы массивов считаются константными указателями (т.е. в данном примереа"имеет значение" 4000).Такую константу можно присвоить переменной типа указатель, но нельзя подвергать преобразованиям, например:

inta[5], *q;

q=a; // Правильно - присваивание константы переменной

a=q; // Ошибка: в левой части - указатель-константа

Именно потому, что имена массивов считаются константными указателями, в языке Си нельзя непосредственно присваивать массивы друг другу (хотя структуры, включающие массивы как поля, целиком присваивать друг другу можно!)

Однако операция sizeof для массивов все же дает размер массива, а не указателя:

int n = sizeof(a) / sizeof(*a);

// n=5, т.к. sizeof(a)=20, sizeof(int)=4

int m = sizeof(q) / sizeof(*q);

// m=1, т.к. sizeof(int*)=4, sizeof(int)=4

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]