Оператор разыменования или оператор косвенного обращения , иногда обозначаемый « *
» (т. Е. Звездочкой ), является унарным оператором (т. Е. С одним операндом), встречающимся в C- подобных языках, которые включают переменные- указатели . Он работает с переменной-указателем и возвращает l-value
эквивалент значения по адресу указателя. Это называется «разыменованием» указателя. Например, код C
int x ; int * p ; // * используется в объявлении: // p - указатель на целое число, поскольку (после разыменования) // * p является целым числом x = 0 ; // теперь x == 0 p = & x ; // & принимает адрес x // теперь * p == 0, поскольку p == & x и, следовательно, * p == x * p = 1 ; // эквивалентно x = 1, поскольку p == & x // теперь * p == 1 и x == 1
присваивается 1 переменной x
с помощью оператора разыменования и указателя на переменную x
.
Состав
Унарный оператор *, как определено в C и C ++ , может использоваться в композициях в случаях множественного косвенного обращения , когда требуется несколько действий разыменования. Указатели, конечно, могут ссылаться на другие указатели, и в таких случаях требуется несколько приложений оператора разыменования. Точно так же оператор точки Java может использоваться в композициях, формирующих довольно сложные операторы, которые требуют существенного разыменования указателей за кулисами во время оценки.
Базовым примером косвенного обращения с несколькими указателями является аргумент argv для основной функции в C (и C ++) , который в прототипе указан как char **argv
. Имя вызываемого исполняемого файла программы, а также все последующие аргументы командной строки сохраняются в виде независимых символьных строк. Массив указателей char
содержит указатели на первый символ каждой из этих строк, и этот массив указателей передается main
функции в качестве argv
аргумента. Сам переданный массив «распадается» на указатель, таким образом argv
, фактически является указателем на указатель на char
, даже несмотря на то , что он обозначает массив указателей на char
(аналогично указатели в массиве, каждый из которых формально указывает на одну char
, фактически точку что такое строки символов). Сопутствующий main
аргумент, argc
предоставляет размер массива (то есть количество строк, на которые указывают элементы массива), поскольку размер (крайнего) массива в противном случае теряется, когда он передается в функцию и преобразуется в указатель. Таким образом, argv
это указатель на 0-й элемент массива указателей на char
, *argv
который, в свою очередь, является указателем на **argv
символ (точнее, 0-й символ первой строки аргумента, который по соглашению является именем программы).
Другой синтаксис
В BCPL , предке C, эквивалентный оператор был представлен с помощью восклицательного знака .
В языке C адрес структуры (или объединения) s
обозначается &s
. Адрес оператора &
обратен оператору разыменования *
, поэтому *&s
эквивалентен s
. Адрес структуры (или объединения) s
может быть назначен указателю p
:
p = & s ; // адрес s был присвоен p; p == & s; // * p эквивалентно s
Значение члена a
структуры s
обозначается s.a
. Данный указатель p
на s
(т.е. p == &s
) s.a
эквивалентен (*p).a
сокращению, p->a
которое является синтаксическим сахаром для доступа к членам структуры (или объединения) через указатель:
p = & s ; // адрес s был присвоен p; p == & s; // sa эквивалентно (* p) .a // sa эквивалентно p-> a // (* p) .a эквивалентно p-> a
->
Оператор может быть цепью; например, в связанном списке можно ссылаться n->next->next
на второй следующий узел (при условии, что n->next
он не равен нулю).
В сценариях оболочки Unix и в таких утилитах, как Makefiles , знак доллара " $
" является оператором разыменования, который используется для преобразования имени переменной в ее содержимое и, что особенно важно, отсутствует при присвоении переменной.
В Паскале оператор разыменования ^ работает как для определения указателя, так и для его разыменования. Как показано в следующем примере:
Тип ComplexP = ^ TComplex ; (* ComplexP - это тип указателя *) TComplex = запись (* TComplex - это тип записи *) Re , Im : целое число ;VAR Complex1 , (* определить два указателя *) Complex2 : ComplexP ; Комплекс : TComplex ; (* определить запись *)начинать Сложный . Re : = 3.14159267 ; Сложный . Im : = 1,5 ; Новый ( Комплекс1 ) ; Комплекс1 ^. Re : = Комплекс . Re ; Комплекс1 ^. Im : = 3,5 ; Новый ( Complex2 ) ; Комплекс2 ^ : = Комплекс ; КОНЕЦ .
В приведенном выше примере
- В строке 2 оператор разыменования ^ используется для определения типа указателя ComplexP .
- В строках 12 и 13 значения присваиваются Re и Im файлов Сложная запись.
- В строке 14 выделяется место для TComplex запись, на которую указывает Комплекс1 ( New - это Pascal-эквивалент языка C. функция malloc () .)
- В строке 15 оператор разыменования ^ используется для копирования значения в Re поле записи Комплекс к Re поле TComplex запись, на которую указывает Комплекс1 .
- В строке 16 оператор разыменования ^ используется для присвоения значения Im поле TComplex запись, на которую указывает Комплекс1 .
- В строке 17 выделяется место для TComplex запись, на которую указывает Комплекс2 .
- В строке 18 весь Сложная запись копируется в TComplex запись, на которую указывает Комплекс2 .
В различных языках префиксы используются в идентификаторах, известных как сигилы . Это не унарные операторы - синтаксически они являются лексической частью идентификатора и имеют разную семантику, такую как указание типа данных идентификатора, но синтаксически похожи на оператор разыменования и могут быть перепутаны с ним. Например, в сценарии оболочки к переменной применяется $FOO
оператор разыменования , а в Perl - скалярная переменная с именем . В PHP FOO - это константа (определяемая пользователем или встроенная), $ FOO - это переменная с именем FOO и $$ FOO - это переменная, имя которой хранится в переменной с именем FOO.$
FOO
$foo
foo