在Delphi中有没有可能实现可变参数列表,如c中的sprintf等,在C中是很容易做到的!(我已经找到方法,大家讨论一下!) (200分)

  • 主题发起人 LiChaoHui
  • 开始时间
L

LiChaoHui

Unregistered / Unconfirmed
GUEST, unregistred user!
Delphi中的Write, WriteLn, SetLength
都是可变参数的函数,而Delphi中的Format函数是用数组作为参数实现的,
可变参数的函数一般都定义在System单元中,
是不是对程序员来说,根本就不可能实现可变参数列表的函数呢?


 
参考一下:

Procedure DoIt(X: Array Of Const);
Var
i: Integer;
J: TVarRec;
Begin
for I := Low(X) to High(X) do begin
J := X;
case j.VType of
vtInteger: ShowMessage(IntToStr(j.VInteger)) ;
vtBoolean: ;
vtChar : ;
vtExtended: ;
vtString : ;
vtPointer : ;
vtPChar : ;
vtObject : ;
vtClass : ;
vtWideChar: ;
vtPWideChar: ;
vtAnsiString: ShowMessage(String(j.VAnsiString));
vtCurrency: ;
vtVariant: ;
vtInterface: ;
vtWideString : ;
vtInt64: ;
end;
end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
DoIt([1,'This Is A String',3,4,5]);
end;
 
有没有不使用数组的?
 
我说的是实现类似于Write SetLength的函数,
参数的个数不确定
 
SetLength不过是函数的重载不是可变参数。
给你一个可变参数的例子
procedure a(Const param);
其实变体型参数更好一些
 
你的说法不对,
SetLength的参数个数可以是任意多个,
如果给多维动态数组分配空间,后面可以加任意多个参数,
你所说的是无类型参数,这个没有什么的
 
我已经找到了如何在Delphi中实现参数个数不确定的方法了,
也明白了为什么Delphi中不允许程序员自己写这样的函数,

这和函数的调用协议有关
下面是各种调用协议的参数入栈顺序和参数清除方式,以及是否利用寄存器传递参数
Directive Parameter order Clean-up Passes parameters in registers?
register Left-to-right Routine Yes
pascal Left-to-right Routine No
cdecl Right-to-left Caller No
stdcall Right-to-left Routine No
safecall Right-to-left Routine No

而Delphi默认采用的是FastCall,是第一种调用方式,
这种方式在函数调用时的时间开销非常小,因为它采用寄存器来传递参数,
效率和一般的跳转差不多,但是当参数较多时,还是会采用入栈的方法
这种调用方式是不支持参数个数不确定的函数定义的,但是Delphi可以将数组作为参数
从而弥补了这一问题

而C语言默认采用cdecl的调用协议,这种调用协议可以实现可变的参数列表,
当然Delphi也可以调用这种协议的外部函数,
可以用C语言编写这种函数,并编译为Obj文件,在Delphi中引入外部函数
当然也可以直接在Delphi中用汇编语言来写,
这需要知道对于可变参数列表在堆栈中的传递情况,
不管怎么说,总算有了方法了,希望哪位高手试验一下,

如果试验成功,贴出代码,可以得分
注意调用外部函数时需要加上 cdecl; varargs; 的指示器(directive)
 
When importing a C++ function that takes a variable number of parameters, use the varargs directive. For example,

function printf(Format: PChar): Integer; cdecl; varargs;

The varargs directive works only with external routines and only with the cdecl calling convention.

 
用default value.如function abc(const a:integer; b:boolean=false):boolean;
 
确实使用默认值的
Procedure testfunc(param1:string ='';param2:intetger =1;param3:boolean =false);
 
我说的不是默认值得这一种
 
多人接受答案了。
 
顶部