русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Операции над указателями (косвенная адресация)


Дата добавления: 2013-12-24; просмотров: 1306; Нарушение авторских прав


Связь указателей и массивов.

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

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

 

int a[5];

 

a

a[0] a[1] a[2] a[3] a[4]

4000 4004 4008 4012 4016

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

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

 

int a[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

 

 

Элементы одного массива хранятся в памяти подряд, поэтому адрес каждого последующего элемента больше адреса предыдущего на размер одного элемента, т.е на 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!

 

 



<== предыдущая лекция | следующая лекция ==>
Определение указателей | Указатели как параметры функций.


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.132 сек.