HTML [44] |
Visual C++ и MFC [21] |
c++ [78] |
php [19] |
Javascript [15] |
C# [51] |
загрузки [0] |
XNA
[10]
создание игр с помощью xna
|
Главная » Статьи » c++ |
Что такое указатели?Шаг за шагом, занятие за занятием... Вот мы с Вами и подошли к одной из интереснейших тем, которые рассматриваются при изучении С++ - УКАЗАТЕЛИ. Указатели широко применяются в С++ - отчасти потому, что в некоторых случаях без них просто не обойтись, а отчасти потому, что программы с ними, обычно, короче и эффективнее. Наряду с goto указатели когда-то были объявлены лучшим средством для написания малопонятных программ. Так оно и есть, если ними пользоваться бездумно. При соблюдении же определенной дисциплины с помощью указателей можно достичь ясности и простоты. Мы попытаемся убедить Вас в этом. Давайте, воспользуемся определением указателя, которое дают авторы языка С - Брайн Керниган и Деннис Ритчи . Указатель -это переменная, содержащая адрес переменной. Звучит хорошо, но как-то запутано... Попробуем сказать по-другому. Указатель -это переменная, содержащая адрес памяти, где расположены другие объекты (переменные, функции и т.п.). Второе определение правильней, так как в действительности указатели могут содержать не только адрес переменной, но и адреса других объектов. Язык С++ позволяет Вам определить объект, который будет содержать указатель на объекты любого основного или производного типа данных. Для определения указателя используется символ * в определении или объявлении объекта. Синтаксис определения указателя имеет вид: класс_хранения спецификация_типа *идентификатор; Символ * в этом контексте означает "указатель на". Приведем несколько примеров: int *iptr; //Определяет указатель на целое значение float *fvals; //Определяет указатель на значение с плавающей точкой char *cp; //Описывает указатель на символ За кулисами...Давайте заглянем за кулисы... Начнем с того, что рассмотрим упрощенную схему организации памяти. Память типичного компьютера представляет собой массив последовательно пронумерованных и проадресованных ячеек, с которыми можно работать по отдельности или связаными кусками. Наверное Вы уже знаете, что память IBM PC совместимых компьютеров делится на 8-битовые байты. Когда мы описываем некоторую переменную или массив, в памяти выделяется непрерывная область для хранения этой переменной. Все строго учтено, поэтому каждый байт пронумерован (нумерация начинается с нуля). Номер байта, с которого начинается в памяти переменная, называется адресом этой переменной . Также об адресе говорят, что он указывает на определенный байт. Таким образом, указатель является просто адресом байта памяти. В языке С++ также предусмотрены операции, которые могут быть использованы для доступа к указателям и для манипулирования ними. Применительно к любому компьютеру верны следующие утверждения: один байт может хранить значение типа char, двухбайтовые ячейки могут рассматриваться как целое типа short, а четырехбайтовые - как целые типа long или int. Указатель это группа ячеек (как правило две или четыре), в которых может храниться адрес. Так, если с имеет тип char, а р – указатель, ссылающйся на с, то ситуация выглядит следующим образом:
Как работать с указателями?..Первый шаг в применении указателя - присвоить ему значение адреса. Для этого надо иметь возможность получить адрес, по которому в памяти расположен какой-то другой объект. Унарный оператор & выдает адрес объекта, так что инструкция р=&с; присваивает адрес ячейки с переменной р (говорят, что р указывает на с или, что то же, р ссылается на с). Оператор & применяется только к объектам, расположенным в пямяти. Его операндом не может быть ни выражение, ни константа. Унарный оператор * есть оператор раскрытия ссылки (или, унарная операция взятия косвенного адреса, или операция разыменования - запоминать ВСЕ необязательно, но знать что это такое - необходимо). Примененный к указателю он выдает объект, на который данный указатель ссылается. Предположим, что х и у целые, а ip- указатель на іnt. Следующие несколько строк показавают, каким образом объявляются указатели и используются операторы & и *. int x=1, y=22, z[10]; int *ip; // ip – указатель на int ip=&x; // тепер ip указывает на х y=*ip; // y тепер равен 1 *ip=0 // x теперь равен 0 ip=&z[0]; //ip тепер указывает на z[0] Описания x, y, и z Вам уже знакомы. Объявление указателя ip int *ip; буквально гласит следующее: выражение * ip есть указатель на целое. Вы, наверное, заметили, что указателю разрешено ссылаться только на объекты заданого типа (существует одно исключение: указатель на void может ссылаться на объекты любого типа, но к такому указателю нельзя применять оператор раскрытия ссылки. Об особенностях использования типа void мы поговорим позже) Рассмотрим вопрос связанный с арифметическими операциями над указателями. Если ip ссылается на х целого типа, то * ip можно использовать в любом месте, где допустимо применение х, например: *ip=*ip+10; //увеличивает ip на 10; Унарные операторы * и & имеют более высокий приоритет, чем арифметческие операторы, так что встретив присваивание y=*ip+1 компилятор возмет то, на что указывает iр и добавит к нему 1, а результат присвоет переменной у. Аналогично *ip+=1 увеличивает на единицу то, на что ссылается ip; те же действия выполняют ++*ip и (*ip)++. В последней записи скобки необходимы, поскольку, если их не будет, увеличится значение самого указателя, а не то, на что он ссылается. Это обусловлено тем, что унарные операторы * и ++ имеют одинаковые приоритет и порядок выполнения - справа налево. И, наконец, так как указатели сами являются переменными, в тексте они могут встречаться и без оператора раскрытия ссылки. Например, если iq есть указатель на int, то iq=ip копирует содержимое ip в iq, чтобы ip и iq ссылались на один и тот же объект. Указатели можно использовать как операнды в арифметических операциях. Если у - указатель, то унарная операция у++; увеличивает его значение; теперь оно явлется адресом следующего элемента. Указатели и целые числа можно складывать. Конструкция y+n (y-указатель, n-целое число) задает адрес n-го объекта, на который указывает у. Это справедливо для указателей на любой тип; компилятор будет масштабировать приращение адреса в соответсвии с типом, определенным из соответсвующего объявления. Любой адрес можно проверить на равенство (==) или неравнство (!=) со специальным значением NULL, которое позволяет определить ничего не адресующий указатель. Заметим, что указатели можно сравнивать с помощью операций отношения (<, >, <=, >=, != и ==). Однако следует быть осторожным, так как в сравнении должны участвовать указатели, которые адресуются к данным одного и того же типа. Зачем нужны указатели?Применение указателей позволяет упростить алгоритм или повысить его эффективность. Каким образом? Указатели могут обесечить простые способы ссылок на массивы, списки или блоки данных. Для таких ссылок достаточно иметь простой элемент данных: указатель. Нередко бывает проще и эффективнее манипулировать простым указателем, чем управлять полным списком данных. Управление памятью компьютера - это еще одно из важнейших применений указателей. | |
Просмотров: 6621 | Рейтинг: 5.0/1 |
Всего комментариев: 0 | |