Spec-Zone.ru › Ada 2005
Справочник по Ada 2005

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 is
pragma Preelaborate(Pointers);
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;
function "+" (Left : in ptrdiff_t; Right : in Pointer) return Pointer;
function "-" (Left : in Pointer; Right : in ptrdiff_t) return Pointer;
function "-" (Left : in Pointer; Right : in Pointer) return ptrdiff_t;
procedure Increment (Ref : in out Pointer);
procedure Decrement (Ref : in out Pointer);
pragma Convention (Intrinsic, "+");
pragma Convention (Intrinsic, "-");
pragma Convention (Intrinsic, Increment);
pragma Convention (Intrinsic, Decrement);
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;
Возвращает количество элементов до первого Terminator в 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 не указывает на алиасированный элемент.
Выполнение Value(Ref, Terminator) является ошибочным, если Ref не указывает на алиасированный элемент в Element_Array, завершённом Terminator.
Выполнение Value(Ref, Length) является ошибочным, если Ref не указывает на алиасированный элемент в Element_Array, содержащем как минимум Length элементов между указанным элементом и концом массива включительно.
Выполнение Virtual_Length(Ref, Terminator) является ошибочным, если Ref не указывает на алиасированный элемент в Element_Array, завершённом Terminator.
Выполнение Copy_Terminated_Array(Source, Target, Limit, Terminator) является ошибочным в следующих ситуациях:
  • Выполнение как Value(Source, Terminator), так и Value(Source, Limit) является ошибочным, или
  • Копирование записывает за пределы массива, содержащего элемент, обозначенный Target.
Выполнение Copy_Array(Source, Target, Length) является ошибочным, если либо Value(Source, Length) ошибочно, либо копирование записывает за пределы массива, содержащего элемент, обозначенный Target.
ПРИМЕЧАНИЯ
12 Чтобы создать указатель 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