如何使用可变参数打印出字符串?

How to use varargs to print out strings?

如何使用可变参数打印出多个字符串?我试过了,但我无法确定数组的大小。它只是打印垃圾。

program Project1;

{$APPTYPE CONSOLE}
{$POINTERMATH ON}

function _Print(const S: String): string; cdecl;
var
  Args: Array[0..100] of Pointer absolute S;
  I: Integer;
begin
  I := 0;
  while Args[I] <> nil do
  begin
    WriteLn(PString(@Args[I])^);
    Inc(I);
  end;
end;

const Print: function(const S: String): string; cdecl varargs = _Print;

var
  A, B: String;
begin
  A := 'ABC';
  B := 'CDE';
  Print(a, b, 'asdasd', 'fasd', ' ')
end.

varargs 函数无法自动确定传递的参数数量,因为只有调用者知道它在调用堆栈中放置了多少参数。该函数必须通过以下方式手动确定参数:

  1. 要求调用者传递实际参数个数作为固定参数:

    function _Print(NumStrings: Integer; const Strings: string): string; cdecl;
    var
      Args: Array[0..100] of Pointer absolute Strings;
      I: Integer;
    begin
      for I := 0 to NumStrings-1 do
      begin
        WriteLn(PString(@Strings[I])^);
      end;
    end;
    
    const
      Print: function(NumStrings: Integer; const Strings: string): string; cdecl varargs = _Print;
    
    var
      A, B: String;
    begin
      A := 'ABC';
      B := 'CDE';
      Print(5, a, b, 'asdasd', 'fasd', ' ');
    end.
    
  2. 将哨兵值放在函数随后可以查找的参数列表的末尾。你的函数已经为此编码(它正在寻找一个 nil 指针),所以只需传递一个:

    Print(a, b, 'asdasd', 'fasd', ' ', nil);
    

也就是说,这两种方法都容易出现调用者错误,因此如果使用不当可能会造成危险,这就是 varargs 风格的函数不常使用的原因。您应该考虑改用 open-array 参数:

program Project1;

{$APPTYPE CONSOLE}
{$POINTERMATH ON}

function _Print(const Args: array of string): string;
var
  I: Integer;
begin
  for I := Low(Args) to High(Args) do
  begin
    WriteLn(Args[I]);
  end;
end;

const
  Print: function(const Args: array of string): string = _Print;

var
  A, B: String;
begin
  A := 'ABC';
  B := 'CDE';
  Print([a, b, 'asdasd', 'fasd', ' ']);
end.