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

28.Операции над указателями и массивами.

Элементы одного массива хранятся в памяти подряд, поэтому адрес каждого последующего элемента больше адреса предыдущего на размер одного элемента, т.е на sizeof(тип)байт, гдетип - тип элемента массива. Поэтому, зная адрес одного элемента, легко вычислить адрес другого.

В языке С программист имеет возможность воспользоваться этим с помощью арифметических операций с указателями,т.е. прибавлением к ним (или вычитанием из них) целой величины:

p+i

p-i

p+=i

p-=i

p++

p--

где: p - указатель, i - целочисленное выражение.

Допускается также вычитание указателей:

p1-p2

где p1, p2 - указатели. Результатом вычитания является целое число.

Чтобы программист не был вынужден при этом каждый раз учитывать размер элемента, в языке Си принято правило: все арифметические операции с указателями выполняются в единицах памяти того типа объекта, на который ссылается этот указатель. Иными словами, операцияp++ означает реальное увеличениеpне на единицу, а на sizeof(*p) ; при этомpкак раз будет указывать на следующий элемент массива. Аналогично, выражениеp+iозначает в действительностиp+ i*sizeof(*p) , т.е. смещение наiэлементов.

Заметим, что из-за этого указатели на объекты разных типов, первоначально равные, могут стать неравными при прибавлении к ним одной и той же величины:

int a[5], *q=a; // i указывает на a[0]

double*d=(double*)q;

// Теперь d=q(не считая разницы в типах)

q++;d++;

// теперь d>q, т.к. хранимый вdадрес

// увеличился на 8, а хранимый в q- на 4

q++; // а теперь сноваd=q, и равно &a[2]

Однако на практике подобная адресация одного и того же участка памяти указателями разных типов редко имеет смысл.

В силу сказанного выше, адрес i-го элемента массиваAвсегда можно записывать и как &A[i], и какA+i. Итак, для массивов записьA[i] и *(A+i) эквивалентна. Для удобства операций с указателями, в языке С введено такое же правило записи и для них:

p[i] равносильно *(p+i)

где p - указатель, i - целочисленное выражение.

Иными словами, для обращения к i-му (считая от места, куда указываетp) элементу массива вместо записи *(p+i) можно писать короче:p[i]. Соответственно, и для указателей, и для массивов запись *pэквивалентнаp[0]

Пример:

inta[5], *q=a; // Инициализацияq:qуказывает наa[0]

//(Здесь * перед qозначает объявление его типа(указатель), а не разадресацию)

q++;

*q=40; // Означаетa[1]=40;

q[3]=70; // Означаетa[4]=70;

q[-1]=22; // Означаетa[0]=22;

Операции с указателями бывают особенно полезны для массивов char. (Напомним, что в любом месте, где допустима строка как массивchar, допустим также указатель наchar). С их помощью можно, например, обратиться к середине строки:

chars[]="Hello,world!";

cout<<s+7; // Будет выведен текст:world!

При сравнении указателей могут использоваться отношения любого вида (">", ">=", "<", "<=", "==", "!="). Наиболее важными видами проверок являются отношения равенства или неравенства. Остальные отношения порядка имеют смысл только для указателей на последовательно размещенные объекты (элементы одного массива).

Разность двух указателей дает число объектов адресуемого ими типа в соответствующем диапазоне адресов. Очевидно, что уменьшаемый и вычитаемый указатель также должны соответствовать одному массиву, иначе результат операции не имеет практической ценности.

Любой указатель можно сравнивать со значением NULL, которое означает недействительный адрес. Значение NULL можно присваивать указателю как признак пустого указателя. NULL заменяется препроцессором на выражение (void *)0.

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