[prev] [prev-tail] [tail] [up]

#### Array of const

In Object Pascal or Delphi mode, Free Pascal supports the Array of Const construction to pass parameters to a subroutine.

This is a special case of the Open array construction, where it is allowed to pass any expression in an array to a function or procedure.

In the procedure, passed the arguments can be examined using a special record:

     Type
        PVarRec = ^TVarRec;
        TVarRec = record
          case VType : Longint of
            vtInteger    : (VInteger: Longint);
            vtBoolean    : (VBoolean: Boolean);
            vtChar       : (VChar: Char);
            vtExtended   : (VExtended: PExtended);
            vtString     : (VString: PShortString);
            vtPointer    : (VPointer: Pointer);
            vtPChar      : (VPChar: PChar);
            vtObject     : (VObject: TObject);
            vtClass      : (VClass: TClass);
            vtAnsiString : (VAnsiString: Pointer);
            vtWideString : (VWideString: Pointer);
            vtInt64      : (VInt64: PInt64);
        end;

Inside the procedure body, the array of const is equivalent to an open array of TVarRec:

     Procedure Testit (Args: Array of const);

     Var I : longint;

     begin
       If High(Args)<0 then
         begin
         Writeln ('No aguments');
         exit;
         end;
       Writeln ('Got ',High(Args)+1,' arguments :');
       For i:=0 to High(Args) do
         begin
         write ('Argument ',i,' has type ');
         case Args[i].vtype of
           vtinteger    :
             Writeln ('Integer, Value :',args[i].vinteger);
           vtboolean    :
             Writeln ('Boolean, Value :',args[i].vboolean);
           vtchar       :
             Writeln ('Char, value : ',args[i].vchar);
           vtextended   :
             Writeln ('Extended, value : ',args[i].VExtended^);
           vtString     :
             Writeln ('ShortString, value :',args[i].VString^);
           vtPointer    :
             Writeln ('Pointer, value : ',Longint(Args[i].VPointer));
           vtPChar      :
             Writeln ('PCHar, value : ',Args[i].VPChar);
           vtObject     :
             Writeln ('Object, name : ',Args[i].VObject.Classname);
           vtClass      :
             Writeln ('Class reference, name :',Args[i].VClass.Classname);
           vtAnsiString :
             Writeln ('AnsiString, value :',AnsiString(Args[I].VAnsiStr
         else
             Writeln ('(Unknown) : ',args[i].vtype);
         end;
         end;
     end;

In code, it is possible to pass an arbitrary array of elements to this procedure:

       S:='Ansistring 1';
       T:='AnsiString 2';
       Testit ([]);
       Testit ([1,2]);
       Testit (['A','B']);
       Testit ([TRUE,FALSE,TRUE]);
       Testit (['String','Another string']);
       Testit ([S,T])  ;
       Testit ([P1,P2]);
       Testit ([@testit,Nil]);
       Testit ([ObjA,ObjB]);
       Testit ([1.234,1.234]);
       TestIt ([AClass]);

If the procedure is declared with the cdecl modifier, then the compiler will pass the array as a C compiler would pass it. This, in effect, emulates the C construct of a variable number of arguments, as the following example will show:

     program testaocc;
     {$mode objfpc}

     Const
       P : Pchar = 'example';
       Fmt : PChar =
             'This %s uses printf to print numbers (%d) and strings.'#10;

     // Declaration of standard C function printf:
     procedure printf (fm : pchar; args : array of const);cdecl; external 'c';

     begin
      printf(Fmt,[P,123]);
     end.

Remark that this is not true for Delphi, so code relying on this feature will not be portable.

[prev] [prev-tail] [front] [up]