![]() |
Главная Случайная страница Контакты | Мы поможем в написании вашей работы! | |
|
Элементы одного массива хранятся в памяти подряд, поэтому адрес каждого последующего элемента больше адреса предыдущего на размер одного элемента, т.е на 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]
Пример:
int a[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). С их помощью можно, например, обратиться к середине строки:
char s[]="Hello, world!";
cout<<s+7; // Будет выведен текст: world!
Дата публикования: 2014-11-04; Прочитано: 294 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!