Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Взаимосвязь между массивами и указателями




Массивы и указатели в Си тесно связаны и могут быть использованы почти эквивалентно. Имя массива можно понимать как константный указатель на первый элемент массива. Его отличие от обычного указателя только в том, что его нельзя модифицировать. Например, задан целочисленный массив A на 5 элементов:

int A[5]={-2,5,4,-17,3};

Посмотрим, как этот массив разместится в оперативной памяти (рисунок 7.1).

  . . .  
A[4]  
  0x0012FF90
 
 
   
A[3]   0x0012FF8C
 
 
   
A[2]   0x0012FF88
 
 
   
A[1]   0x0012FF84
 
 
   
A[0]   0x0012FF80
 
 
  . . .  
const int *A   0х0012FF70
 
 
 
  . . .

Рисунок 7.1 – Представление массива элементов в памяти ЭВМ

 

Обратите внимание, что под хранение значения каждого элемента массива выделяется четыре ячейки памяти, что видно из чередования адресов ячеек памяти через четыре байта. Это связано с тем, что тип этого массива – int. Причем, под хранение адреса начала массива выделяется тоже четыре байта, так как все указатели для 32-разрядных процессоров 4-х байтные.

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

int b[5] = {1,2,3,4,5}, *Pt;

Тем самым вы объявили массив целых чисел b[5] и указатель на целое Pt. Поскольку имя массива является указателем на первый элемент массива, вы можете задать указателю Pt адрес первого элемента массива b с помощью оператора Pt = b;

Это эквивалентно присваиванию адреса первого элемента массива следующим образом: Pt = &b[0];

Теперь можно сослаться на элемент массива b[3] с помощью выражения *(Pt + 3).

Указатели можно индексировать точно так же, как и массивы. Например, выражение Pt[3] ссылается на элемент массива b[3].

Или, например, определение int a[5];задает массив из пяти элементов а[0], a[1], a[2], a[3], a[4]. Если объект *у определен как

int *у;

то оператор

у = &a[0];

присваивает переменной у адрес элемента а[0]. Если переменная у указывает на очередной элемент массива а, то y+1 указывает на следующий элемент, причем здесь выполняется соответствующее масштабирование для приращения адреса с учетом длины объекта (для типа int – 4 байта,long - 4 байта, (double - 8 байт и т.д.).

Так как само имя массива есть адрес его нулевого элемента, то оператор у = &a[0]; можно записать и в другом виде: у = а. Тогда элемент а[1] можно представить как *(а+1). С другой стороны, если у - указатель на массив a, то следующие две записи: a[i] и *(у+i) эквивалентны. Рассмотрим пример:

int main(int argc, char* argv[])

{

int a[5]={-5,0,34,12,-17};

cout<<endl<<(a+2); // оператор 1

cout<<endl<<&a[2]; // оператор 2

cout<<endl<<*(a+2); // оператор 3

cout<<endl<<a[2]; // оператор 4

cout<<endl;

return 0;

}

Так, операторы 1 и 2 выведут одно и то же значение – адрес элемента массива с индексом 2. А операторы 3 и 4 – одно и то же значение 34.

Между именем массива и соответствующим указателем есть одно важное различие. Указатель - это переменная и у = а или y++ - допустимые операции. Имя же массива - константа, поэтому конструкции вида a = y, a++ использовать нельзя, так как значение константы постоянно и не может быть изменено.

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

С указателями может выполняться ограниченное количество арифметических операций. Указатель можно увеличивать (++), уменьшать (--), складывать с указателем целые числа (+ или +=), вычитать из него целые числа (- или -=) или вычитать один указатель из другого.

Сложение указателей с целыми числами отличается от обычной арифметики. Прибавить к указателю 1 означает сдвинуть его на число байтов, содержащихся в переменной, на которую он указывал. Обычно подобные операции применяются к указателям на массивы. Если продолжить приведенный выше пример, в котором указателю Pt было присвоено значение b - указателя на первый элемент массива, то после выполнения оператора

Pt += 2;

Pt будет указывать на третий элемент массива b. Истинное же значение указателя Pt изменится на число байтов, занимаемых одним элементом массива, умноженное на 2. Например, если каждый элемент массива b занимает 2 байта, то значение Pt (т.е. адрес в памяти, на который указывает Pt) увеличится на 4.

Аналогичные правила действуют и при вычитании из указателя целого значения.

Переменные указатели можно вычитать один из другого. Например, если Pt указывает на первый элемент массива b, а указатель Pt1 - на третий, то результат выражения Pt1 - Pt будет равен 2 - разности индексов элементов, на которые указывают эти указатели. И так будет, несмотря на то, что адреса, содержащиеся в этих указателях, различаются на 4 (если элемент массива занимает 2 байта).

Арифметика указателей теряет всякий смысл, если она выполняется не над указателями на массив. Сравнение указателей операциями >, <, >=, <= также имеют смысл только для указателей на один и тот же массив. Однако, операции отношения == и!= имеют смысл для любых указателей. При этом указатели равны, если они указывают на один и тот же адрес в памяти.




Поделиться с друзьями:


Дата добавления: 2014-11-16; Просмотров: 777; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




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