14.4.6 Массив констант

На верх  Назад  Вперёд

Free Pascal в режиме Object Pascal  или Delphi, поддерживает конструкцию Array of Const (массив констант) для передачи параметров в подпрограмму.

Это частный случай конструкции Open array (открытого массива), так он может передать любое выражение в функцию (или процедуру). Тип результата выражения должен быть простым: структура не может быть переданы как аргумент. Это означает, что могут быть переданы порядковые и вещественные типы, строки, а также указатели на классы и интерфейсы.

Элементы array of const преобразуются в специальную вариантную запись:

Type

PVarRec = ^TVarRec;

TVarRec = record

    case VType : Ptrint of

      vtInteger   : (VInteger: Longint);

      vtBoolean   : (VBoolean: Boolean);

      vtChar       : (VChar: Char);

      vtWideChar   : (VWideChar: WideChar);

      vtExtended   : (VExtended: PExtended);

      vtString     : (VString: PShortString);

      vtPointer   : (VPointer: Pointer);

      vtPChar     : (VPChar: PChar);

      vtObject     : (VObject: TObject);

      vtClass     : (VClass: TClass);

      vtPWideChar : (VPWideChar: PWideChar);

      vtAnsiString : (VAnsiString: Pointer);

      vtCurrency   : (VCurrency: PCurrency);

      vtVariant   : (VVariant: PVariant);

      vtInterface : (VInterface: Pointer);

      vtWideString : (VWideString: Pointer);

      vtInt64     : (VInt64: PInt64);

      vtQWord     : (VQWord: PQWord);

  end;

Внутри тела процедуры аргумент array of const эквивалентен открытому массиву TVarRec:

Procedure Testit (Args: Array of const);

Var I : longint;

begin

If High(Args)<0 then

  begin

  Writeln ('Нет аргументов');

  exit;

  end;

Writeln ('Got ',High(Args)+1,' arguments :');

For i:=0 to High(Args) do

  begin

  write ('Аргумент ',i,' имеет тип ');

  case Args[i].vtype of

    vtinteger   :

      Writeln ('Целое, Со значением :',args[i].vinteger);

    vtboolean   :

      Writeln ('Boolean, Со значением :',args[i].vboolean);

    vtchar       :

      Writeln ('Символ, Со значением : ',args[i].vchar);

    vtextended   :

      Writeln ('Вещественное, Со значением : ',args[i].VExtended^);

    vtString     :

      Writeln ('ShortString, Со значением :',args[i].VString^);

    vtPointer   :

      Writeln ('Указатель,, Со значением : ',Longint(Args[i].VPointer));

    vtPChar     :

      Writeln ('PChar,, Со значением : ',Args[i].VPChar);

    vtObject     :

      Writeln ('Объект, С именем : ',Args[i].VObject.Classname);

    vtClass     :

      Writeln ('Ссылка на класс, С именем :',Args[i].VClass.Classname);

    vtAnsiString :

      Writeln ('AnsiString, Со значением :',AnsiString(Args[I].VAnsiString);

  else

      Writeln ('(Неизвестное) : ',args[i].vtype);

  end;

  end;

end;

В код этой процедуры можно передать произвольный массив элементов:

S:='AnsiString 1';

T:='AnsiString 2';

Testit ([]);

Testit ([1,2]);

Testit (['A','B']);

Testit ([TRUE,FALSE,TRUE]);

Testit (['String','Иная строка']);

Testit ([S,T]) ;

Testit ([P1,P2]);

Testit ([@testit,Nil]);

Testit ([ObjA,ObjB]);

Testit ([1.234,1.234]);

TestIt ([AClass]);

Если процедура объявлена с модификатором cdecl, то компилятор будет передать массив как откомпилированный под С. Он, эмулирует C конструкцию с переменным числом аргументов, как показано в следующем примере:

program testaocc;

{$mode objfpc}

 

Const

P : PChar = 'пример';

Fmt : PChar =

      'Этот %s показывает использование printf для вывода чисел (%d) и строк'#10;

// Объявление стандартной функции printf:

 

procedure printf (fm : pchar; args : array of const);cdecl; external 'c';

begin

printf(Fmt,[P,123]);

end.

Заметим, что это не верно для Delphi, поэтому код опирающйся на эту функцию не будет переносим.

Примечание:

Обратите внимание , что не существует поддержки аргументов QWord в array of const. Это нужно для совместимости с Delphi, и компилятор будет игнорировать проверку диапазона в режиме Delphi.