Радиоконструктор

Язык C, Часть 27

Указатели

Правильное понимание и использование указателей особенно необходимо для составления хороших программ на языке С. И вот почему. Во-первых, указатели являются средством, с помощью которого функция может изменять значения передаваемых в нее аргументов. Во-вторых, с помощью указателей выполняется динамическое распределение памяти. В-третьих, указатели позволяют повысить эффективность многих процедур. И наконец, они обеспечивают поддержку динамических структур данных, таких, например, как двоичные деревья и связные списки.
Таким образом, указатели являются весьма мощным средством языка С. Но и весьма опасным. Например, если указатель содержит неправильное значение, программа может потерпеть крах. Указатели весьма опасны еще и потому, что легко ошибиться при их использовании. К тому же ошибки, связанные с неправильными значениями указателей, найти очень трудно. 


Что такое указатели

Указатель — это переменная, значением которой является адрес некоторого объекта (обычно другой переменной) в памяти компьютера. Например, если одна переменная содержит адрес другой переменной, то говорят, что первая переменная указывает (ссылается) на вторую. Это иллюстрируется с помощью рис. 5.1.
Рис. 5.1. Одна переменная ссылается на другую
Адрес     Значение
ячейки  переменной в
памяти     памяти
        +----------+
1000    |   1003   |--.
        +----------+  |
1001    |          |  |
        +----------+  |
1002    |          |  |
        +----------+  |
1003    |          |<-'
        +----------+
1004    |          |
        +----------+
1005    |          |
        +----------+
1006    |          |
        +----------+
             .
             .
             .
           Память

Указательные переменные

Как известно, переменную, являющуюся указателем, нужно соответствующим образом объявить. Объявление указателя состоит из имени базового типа, символа * и имени переменной. Общая форма объявления указателя следующая:
тип *имя;
Здесь тип — это базовый тип указателя, им может быть любой правильный тип. Имя определяет имя переменной-указателя.
Базовый тип указателя определяет тип объекта, на который указатель будет ссылаться. Фактически указатель любого типа может ссылаться на любое место в памяти. Однако выполняемые с указателем операции существенно зависят от его типа. Например, если объявлен указатель типа int *, компилятор предполагает, что любой адрес, на который он ссылается, содержит переменную типа int, хоть это может быть и не так. Следовательно, объявляя указатель, необходимо убедиться, что его тип совместим с типом объекта, на который он будет ссылаться. 

Операции для работы с указателями

Операции для работы с указателями рассматривались в главе 2. Приведем их обзор. В языке С определены две операции для работы с указателями: * и &. Оператор & — это унарный оператор, возвращающий адрес своего операнда. (Напомним, что унарный оператор имеет один операнд). Например, оператор
m = &count;
присваивает переменной m адрес переменной count. Можно сказать, что адрес — это номер первого байта участка памяти, в котором хранится переменная. Адрес и значение переменной — это совершенно разные понятия. Оператор & можно представить себе как оператор, возвращающий адрес объекта. Следовательно, предыдущий пример можно прочесть так: "переменной m присваивается адрес переменной count".
Предположим, переменная count хранится в ячейке памяти под номером 2000, а ее значение равно 100. Тогда переменной m будет присвоено значение 2000.
Вторая операция для работы с указателями (ее знак, т.е. оператор, *) выполняет действие, обратное по отношению к &. Оператор * — это унарный оператор, возвращающий значение переменной, расположенной по указанному адресу. Например, если m содержит адрес переменной count, то оператор
q = *m;
присваивает переменной q значение переменной count. Таким образом, q получит значение 100, потому что по адресу 2000 расположена переменная count, которая имеет значение 100. Действие оператора * можно выразить словами "значение по адресу", тогда предыдущий оператор может быть прочитан так: "q получает значение переменной, расположенной по адресу m".

Комментарии