Spec-Zone.ru › Ada 2022
Руководство по Ada (Ada 2022)

B.3.2 Обобщённый пакет интерфейсов.C.Указатели

Обобщённый пакет Interfaces.C.Pointers позволяет программисту Ada выполнять операции в стиле C с указателями. Он включает в себя тип доступа Pointer, функции Value, которые разыменовывают указатель Pointer и возвращают указанный массив, несколько операций арифметики указателей и процедуры «копирования», которые копируют содержимое исходного указателя в массив, указанный целевым указателем. Как и в C, он обрабатывает объект Ptr типа Pointer как указатель на первый элемент массива, так что, например, добавление 1 к Ptr даёт указатель на второй элемент массива.
Обобщённый пакет допускает два стиля использования: один, в котором массив завершается специальным терминатором; и другой, в котором программист отслеживает длину.

Статическая семантика

Обобщённый пакет библиотеки Interfaces.C.Pointers имеет следующее объявление:
generic
type Index is (<>);
type Element is private;
type Element_Array is array (Index range <>) of aliased Element;
Default_Terminator : Element;
package Interfaces.C.Pointers
with Preelaborate, Nonblocking, Global => in out synchronized is
type Pointer is access all Element;
function Value(Ref : in Pointer;
Terminator : in Element := Default_Terminator)
return Element_Array;
function Value(Ref : in Pointer;
Length : in ptrdiff_t)
return Element_Array;
Pointer_Error : exception;
-- Арифметика указателей в стиле C
function "+" (Left : in Pointer; Right : in ptrdiff_t) return Pointer
with Convention => Intrinsic;
function "+" (Left : in ptrdiff_t; Right : in Pointer) return Pointer
with Convention => Intrinsic;
function "-" (Left : in Pointer; Right : in ptrdiff_t) return Pointer
with Convention => Intrinsic;
function "-" (Left : in Pointer; Right : in Pointer) return ptrdiff_t
with Convention => Intrinsic;
procedure Increment (Ref : in out Pointer)
with Convention => Intrinsic;
procedure Decrement (Ref : in out Pointer)
with Convention => Intrinsic;
Этот абзац был удалён.
function Virtual_Length (Ref : in Pointer;
Terminator : in Element := Default_Terminator)
return ptrdiff_t;
procedure Copy_Terminated_Array
(Source : in Pointer;
Target : in Pointer;
Limit : in ptrdiff_t := ptrdiff_t'Last;
Terminator : in Element := Default_Terminator);
procedure Copy_Array (Source : in Pointer;
Target : in Pointer;
Length : in ptrdiff_t);
end Interfaces.C.Pointers;
Тип Pointer совместим с C и соответствует одному использованию «Element *» C. Объект типа Pointer интерпретируется как указатель на начальный элемент Element в Element_Array. Поддерживаются два стиля:
  • Явное завершение значения массива Default_Terminator (специальное значение терминатора);
  • Управление длиной программистом, при этом Default_Terminator рассматривается просто как элемент данных.
function Value(Ref : in Pointer;
Terminator : in Element := Default_Terminator)
return Element_Array;
Эта функция возвращает Element_Array, значение которого является массивом, на который указывает Ref, вплоть до и включая первый Terminator; нижняя граница массива — Index'First. Interfaces.C.Strings.Dereference_Error распространяется, если Ref — null.
function Value(Ref : in Pointer;
Length : in ptrdiff_t)
return Element_Array;
Эта функция возвращает Element_Array, содержащий первые Length элементов, на которые указывает Ref. Исключение Interfaces.C.Strings.Dereference_Error распространяется, если Ref — null.
Функции «+» и «–» выполняют арифметические операции над значениями Pointer, основанные на размере элементов массива. В каждой из этих функций Pointer_Error распространяется, если параметр Pointer равен null.
procedure Increment (Ref : in out Pointer);
Эквивалентно Ref := Ref+1.
procedure Decrement (Ref : in out Pointer);
Эквивалентно Ref := Ref–1.
function Virtual_Length (Ref : in Pointer;
Terminator : in Element := Default_Terminator)
return ptrdiff_t;
Возвращает количество элементов, до первого терминатора, в Value(Ref, Terminator).
procedure Copy_Terminated_Array
(Source : in Pointer;
Target : in Pointer;
Limit : in ptrdiff_t := ptrdiff_t'Last;
Terminator : in Element := Default_Terminator);
Эта процедура копирует Value(Source, Terminator) в массив, на который указывает Target; она останавливается либо после копирования Terminator, либо после копирования Limit элементов, в зависимости от того, что произойдёт раньше. Dereference_Error распространяется, если Source или Target равны null.
procedure Copy_Array (Source : in Pointer;
Target : in Pointer;
Length : in ptrdiff_t);
Эта процедура копирует первые Length элементов из массива, на который указывает Source, в массив, на который указывает Target. Dereference_Error распространяется, если Source или Target равны null.

Ошибочное выполнение

Дераференция Pointer, не указывающего на алиасированный Element, является ошибочной.
Выполнение Value(Ref, Terminator) является ошибочным, если Ref не указывает на алиасированный Element в Element_Array, завершённый Terminator.
Выполнение Value(Ref, Length) является ошибочным, если Ref не указывает на алиасированный Element в Element_Array, содержащем по меньшей мере Length элементов между указанным элементом и концом массива включительно.
Выполнение Virtual_Length(Ref, Terminator) является ошибочным, если Ref не указывает на алиасированный Element в Element_Array, завершённый Terminator.
Выполнение Copy_Terminated_Array(Source, Target, Limit, Terminator) является ошибочным в следующих ситуациях:
  • Выполнение как Value(Source, Terminator), так и Value(Source, Limit) является ошибочным, или
  • Копирование записывает данные за пределы массива, содержащего Element, на который указывает Target.
Выполнение Copy_Array(Source, Target, Length) является ошибочным, если либо Value(Source, Length) является ошибочным, либо копирование записывает данные за пределы массива, содержащего Element, на который указывает Target.
ПРИМЕЧАНИЕ Для создания Pointer из Element_Array, используйте 'Access первого элемента. Например (при соответствующих инстанцированиях):
Some_Array : Element_Array(0..5) ;
Some_Pointer : Pointer := Some_Array(0)'Access;

Примеры

Пример Interfaces.C.Pointers:
with Interfaces.C.Pointers;
with Interfaces.C.Strings;
procedure Test_Pointers is
package C renames Interfaces.C;
package Char_Ptrs is
new C.Pointers (Index => C.size_t,
Element => C.char,
Element_Array => C.char_array,
Default_Terminator => C.nul);
use type Char_Ptrs.Pointer;
subtype Char_Star is Char_Ptrs.Pointer;
procedure Strcpy (Target_Ptr, Source_Ptr : Char_Star) is
Target_Temp_Ptr : Char_Star := Target_Ptr;
Source_Temp_Ptr : Char_Star := Source_Ptr;
Element : C.char;
begin
if Target_Temp_Ptr = null or Source_Temp_Ptr = null then
raise C.Strings.Dereference_Error;
end if;
loop
Element := Source_Temp_Ptr.all;
Target_Temp_Ptr.all := Element;
exit when C."="(Element, C.nul);
Char_Ptrs.Increment(Target_Temp_Ptr);
Char_Ptrs.Increment(Source_Temp_Ptr);
end loop;
end Strcpy;
begin
...
end Test_Pointers;


Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API