大虾们,能否不用变量名访问变量?(150分)

  • 主题发起人 主题发起人 zv2000
  • 开始时间 开始时间
Z

zv2000

Unregistered / Unconfirmed
GUEST, unregistred user!
在程序中定义了变量,系统便会把它放在栈或什么地方,然后当你在程序中用变量名
去访问变量时,系统便会根据变量名找到存放变量的地方,取出值,那么这个过程我
能否自己在程序中实现呢?
我用delphi时间不长,刚才看了有人提问,如何实现类似foxpro中的宏替换功能,很
多人说不可能实现,我想,delphi功能如此强大,怎么连解释语言能实现的功能都实
现不了呢?而且,foxpro的宏替换功能的确很实用、好用,区区以为,上面提出的问
题如果能够解决,那宏替换一样能够解决,如果有人能回答,我愿意奉上150分。
拜托各位了。
 
补充一下,我没有学过《编译原料》,但foxpro是用c编的,所以,我觉得,用编译语言
是应该能够实现的。
 

用汇编语言当然可以实现,一般来说,编译器会尽可能
将参数及局部变量放进寄存器中,顺序是EAX->EDX->ECX,
剩下的才压入堆栈:函数内声明的变量会放在EBP 的负
偏移,参数会放在EBP 的正偏移。

但要注意很多例外的地方,比方说当函数定义为stdcall,
cdecl,safecall时所有的参数都压栈,而且压栈顺序为从右
向左。

这部分的内容可以参考Delphi所附帮助中
Object Pascal Refrence -> Program Control
 
或者你可以试试着这样:

定义变量的绝对地址:
var CrtMode: Byte absolute $0040;

定义变量的别名:
var
Str: string[32];
StrLen: Byte absolute Str;

这都是用关键字Absolute事先的,具体可以参照一下帮助文件。
 
但是,我在interface定义两个变量,如:var s,h:string;,我怎么知道栈或寄存器
中的值是 s 还是 h 的值呢?系统应该有张“变量名 --> 地址”的对应表吧!
 
有一个相对简单的解决办法,不过效率及其低下(解释型嘛,要求就不要太高了)。
用一个排序的(可以提高查询速度)TStringList存放对象以及对象的名称(这个名称绝对不允许重复),
在使用时,就可以通过对象的名称(字符串)查到对应的对象,对其进行操作。此方法绝对是可行的,
只不过仅能用于变量是对象的情况(对于普通变量,可以通过对其进行包装使其变成对象),如要实现
函数的“宏替换”,估计就要使用函数指针了。

>系统应该有张“变量名 --> 地址”的对应表吧
不错。可那个表仅存在于编译过程之中,在目标代码中,绝大多数变量都变成了毫无意义的偏移量。
 
to creation-zy:
能麻烦你给我个简单的“函数指针”的例子吗?我想知道“函数指针”如何使用,谢谢!
 
function FuncA:Integer;
begin
Result:=123;
end;
function FuncB:Integer;
begin
Result:=321;
end;
function F(Str:String):String;
begin
Result:=Str;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
P:Function:Integer;
P1:Function(Str:String):String;
begin
P:=FuncA;
Caption:=IntToStr(P);
P:=FuncB;
P1:=F;
Caption:=Caption+' '+IntToStr(P)+' '+P1('hehe!');
end;
 
不是实现不了,而是都可以用更有效率的办法实现。
 
看了上面的例子,p=funca,p1=f
我想问的是这在实际应用中有什么作用?
 
看了上面的例子,p=funca,p1=f,只是把函数变了个名子而已。
我想问的是这在实际应用中有什么作用?
 
to yanghaijun
请说。
 
一般来说, 编译型语言在运行时是不存在变量地址的映射表的, 但是Delphi的RTTI里面
是拥有这些信息的, 你可以通过RTTI来访问变量的名称类型以及值等信息. 具体你可以
参考:
unit MainFrm;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TMainForm = class(TForm)
lbSamps: TListBox;
memInfo: TMemo;
procedure FormCreate(Sender: TObject);
procedure lbSampsClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
MainForm: TMainForm;

implementation
uses TypInfo, Buttons;

{$R *.DFM}


procedure TMainForm.FormCreate(Sender: TObject);
begin
// Add some example enumerated types
with lbSamps.Items do
begin
AddObject('TButtonState', TypeInfo(TButtonState));
AddObject('TFormStyle', TypeInfo(TFormStyle));
AddObject('Boolean', TypeInfo(Boolean));
end;
end;

procedure TMainForm.lbSampsClick(Sender: TObject);
var
OrdTypeInfo: PTypeInfo;
OrdTypeData: PTypeData;

TypeNameStr: String;
TypeKindStr: String;
MinVal, MaxVal: Integer;
i: integer;
begin
memInfo.Lines.Clear;
with lbSamps do
begin

// Get the TTypeInfo pointer
OrdTypeInfo := PTypeInfo(Items.Objects[ItemIndex]);
// Get the TTypeData pointer
OrdTypeData := GetTypeData(OrdTypeInfo);

// Get the type name string
TypeNameStr := OrdTypeInfo.Name;
// Get the type kind string
TypeKindStr := GetEnumName(TypeInfo(TTypeKind), Integer(OrdTypeInfo^.Kind));

// Get the minimum and maximum values for the type
MinVal := OrdTypeData^.MinValue;
MaxVal := OrdTypeData^.MaxValue;


// Add the information to the memo
with memInfo.Lines do
begin
Add('Type Name: '+TypeNameStr);
Add('Type Kind: '+TypeKindStr);

Add('Min Val: '+IntToStr(MinVal));
Add('Max Val: '+IntToStr(MaxVal));

// Show the values and names of the enumerated types
if OrdTypeInfo^.Kind = tkEnumeration then
for i := MinVal to MaxVal do
Add(Format(' Value: %d Name: %s', [i, GetEnumName(OrdTypeInfo, i)]));

end;
end;
end;

end.
 
to tseug:
谢谢你的回答,delphi关于RTTI的帮助,几乎没有,而且也只能得到变量的TypeInfo,
无法获取变量的值,或指针,不过我觉得RTTI也许是解决这个问题的途径,能再给些帮助
吗?还有yanghaijun兄?
 
to 阿梁:
>在实际应用中有什么作用?
答案是:宏替换。例如: 'A 加 B' 与 'A 乘 B',我们可以事先用一个StringList存放函数名
与函数指针(一一对应),在解释的时候,就可以根据具体情况针对不同的表达是应用不同的处理
过程。(同样的,还可以针对不同的变量进行替换)
另:RTTI好像仅对对象变量起作用,对于普通变量就不行了。
我没有用过Foxpro,能不能举一个宏替换的例子(实际中可能用到的,可别太极端了)。
 
RTTI只能使用在从TObject对象继承来的对象上。对于宏替换,如果简单的处理,可采用楼上
所说的查表办法;如果有复杂的语法,就要进行词法、语法分析了,网上有范例,你可以去
查。
 
to tseug:
哪儿有范例?
 
这样的范例好像没有!?
 
to 阿梁、creation-zy:
foxpro提供宏替换的功能当然是有其应用的,我想宏替换可能部分替代了指针的作用,
而现在用指针却不能实现宏替换的功能,如:我们不能由一串文本定位到内存中与这串文本
同名的变量的地址,从而访问它。foxpro中用宏替换甚至可以在程序运行中创建新变量。
宏替换在foxpro中的应用是非常广的,但长时间不用了,现在也很难说出些具体的应
用,总之,如果你用过foxpro,你一定会对其强大的宏替换功能留下深刻的印象,并会设
法在其他语言中找寻与之相同、相近的功能。现在的程序员中有很多都是用过foxpro的,
并且对宏替换有着强烈的好感,所以这里才会有这么多关于宏替换在delphi中实现的问题。
如果各位高手能够解答这个问题的话,下面的地址给的分更高,而我没有给更高的分
是因为我以为这个问题在delphi中比较容易实现。
http://www.delphibbs.com/delphibbs/DispQ.asp?LID=592902
 
后退
顶部