Указатели
Указатель - это тип данных, который содержит адрес памяти. Хотя переменная напрямую обращается к этому адресу памяти, указатель можно рассматривать как ссылку на этот адрес памяти.
Чтобы объявить тип данных указателя, добавьте префикс carat (^) перед типом. Например, чтобы создать указатель наinteger
, запишите:
^integer;
Чтобы получить доступ к данным в ячейке памяти указателя, добавьте карат после имени переменной. Например, давайте объявим переменную p, которая указывает на word, а затем присвойте значение 5 указанной ячейке памяти:
var p : ^word; ... p^ := 5;
Указатель может быть назначен другому указателю. Однако обратите внимание, что копируется только адрес, а не значение. После изменения данных, расположенных на одном указателе, другой указатель, при разыменовании, также дает измененные данные.
Указатели и пространства памяти
Указатели могут указывать на данные в любом доступном пространстве памяти.
Указатели могут находиться в любом доступном пространстве памяти, кроме программного пространства (кода).
var ptr1: ^const byte; // ptr1 указатель в пространстве данных, указывающий на байт в кодовом пространстве var ptr2: ^const ^volatile sfr byte; rx; // ptr2 является указателем в пространстве rx, указывающим на указатель в кодовом пространстве, указывающий на произвольный байт в sfr-пространстве var ptr3: ^data byte; code; // ошибка, указатели не могут быть помещены в кодовое пространство
Из-за обратной совместимости указатели на программную память также могут быть объявлены в блоке константного объявления (с использованием зарезервированного слова const
):
program const_ptr; // массив констант будет сохранен в памяти программы const b_array: array[5] of byte = (1,2,3,4,5); const ptr: ^byte; // ptr является указателем на пространство программной памяти begin ptr := @b_array; // ptr now points to b_array[0] GPIO_PORTA := ptr^; ptr := ptr + 3; // ptr now points to b_array[3] GPIO_PORTA := ptr^; end.
Это приводит к равенству следующих деклараций:
var ptr1 : ^const byte; // ptr1 указатель в пространстве данных, указывающий на байт в кодовом пространстве const ptr2 : ^byte; // ptr2 указатель в пространстве данных, указывающий на байт в кодовом пространстве
Следовательно, при объявлении указателя в блоке константного объявления конструктор констант ссылается на заостренный объект, а не на указатель.
- Указатель на постоянное пространство (флэш-память) выделяется в ОЗУ.
- Константы простого типа не выделяются во флэш-памяти или в ОЗУ, но изменяются во время компиляции, и поэтому адрес такой константы не может быть получен.
Указатели функций
Указатели функций разрешены в mikroPascal PRO для ARM. В этом примере показано, как определить и использовать указатель функции:
Пример:
Пример демонстрирует использование указателей функций. Показывается, как объявить процедурный тип, указатель на функцию и, наконец, как вызвать функцию с помощью указателя.
program Example; type TMyFunctionType = function (param1, param2: byte; param3: word) : word; // Сначала определяем процедурный тип var MyPtr: ^TMyFunctionType; // Tего указатель на ранее определенный тип Sample: word; function Func1(p1, p2: byte; p3: word): word; // Теперь определяем несколько функций, на которые будет указано. Убедимся в том, что параметры соответствуют определению типа begin result := p1 and p2 or p3; // возвращает что-то end; function Func2(abc: byte; def: byte; ghi: word): word; // Другая функция того же рода. Убедимся в том, что параметры соответствуют определению типа begin result := abc * def + ghi; // возвращает что-то end; function Func3(first, yellow: byte; monday: word): word; // Еще одна функция. Убедимся в том, что параметры соответствуют определению типа begin result := monday - yellow - first; // возвращает что-то end; // основная программа: begin MyPtr := @Func1; // MyPtr теперь указывает на Func1 Sample := MyPtr^(1, 2, 3); // Выполняем вызов функции через указатель, вызов Func1, возвращаемое значение равно 3 MyPtr := @Func2; // MyPtr теперь указывает на Func2 Sample := MyPtr^(1, 2, 3); // Выполняем вызов функции с помощью указателя, вызовите Func2, возвращаемое значение равно 5 MyPtr := @Func3; // MyPtr теперь указывает на Func3 Sample := MyPtr^(1, 2, 3); // Выполняем вызов функции с помощью указателя, вызовите Func3, возвращаемое значение равно 0 end.
Следовательно, при объявлении указателя в блоке константного объявления конструктор констаны ссылается на указанный объект, а не на указатель.
Оператор @
Оператор @ создает указатель на его операнд. Следующие правила применяются к @:
- Если X является переменной, @X возвращает указатель на X.
Примечание: Если переменная X имеет тип массива, оператор @ вернет указатель на первый базовый элемент, за исключением того, что левая часть оператора, в котором используется X, является указателем массива.
В этом случае оператор @ вернет указатель на массив, а не на его первый базовый элемент.program example; var w : word; ptr_b : ^byte; ptr_arr : ^array[10] of byte; arr : array[10] of byte; begin ptr_b := @arr; // @ оператор вернет ^ байт w := @arr; // @ оператор вернет ^ байт ptr_arr := @arr; // @ оператор вернет ^array[10] of byte end.
- Если F является подпрограммой (функция или процедура), @F возвращает указатель на F.