德尔福:记录领域的偏移
发布时间:2020-12-15 10:08:54 所属栏目:大数据 来源:网络整理
导读:我正在寻找在Delphi记录中获取字段偏移的方法.以下2种方法有效,但我希望能够更清洁.基本上我会喜欢第三次showmessage工作.有任何想法吗? type rec_a=record a:longint; b:byte; c:pointer; end;{$warnings off}function get_ofs1:longint;var abc:^rec_a;be
我正在寻找在Delphi记录中获取字段偏移的方法.以下2种方法有效,但我希望能够更清洁.基本上我会喜欢第三次showmessage工作.有任何想法吗?
type rec_a=record a:longint; b:byte; c:pointer; end; {$warnings off} function get_ofs1:longint; var abc:^rec_a; begin result:=longint(@abc.c)-longint(abc); end; {$warnings on} function get_ofs2:longint; asm mov eax,offset rec_a.c end; procedure TForm1.Button1Click(Sender: TObject); begin showmessage(inttostr(get_ofs1)); showmessage(inttostr(get_ofs2)); // showmessage(inttostr(longint(addr(rec_a.c)))); // is there a way to make this one work? end; 编辑: ---- result:=longint(@abc.c)-longint(abc); ---- lea edx,[eax+$08] sub edx,eax mov eax,edx ---- mov eax,offset rec_a.c ---- mov eax,$00000008 ---- result:=longint(@rec_a(nil^).c); ---- xor eax,eax add eax,$08 编辑2:看起来像以前的问题的复制:previous similar question,如RRUZ所述.如图所示,另一种方法是声明一个全局变量并使用它,如下所示.奇怪的是,编译器仍然无法在编译时分配正确的值,如汇编器输出中所见,因此对于效率和可读性,最好使用nil方法. ---- var ---- ---- rec_a_ofs:rec_a; ---- ---- ... ---- ---- result:=longint(@rec_a_ofs.c)-longint(@rec_a_ofs); ---- mov eax,$0045f5d8 sub eax,$0045f5d0 edit3:好的修改代码,所有知道的方式来完成这个.请注意,第3,第4和第5(类方法)方式生成的汇编代码是否相同,无论是否内联.选择你最喜欢的方式,当你做这些东西! type prec_a=^rec_a; rec_a=record a:longint; b:byte; c:pointer; class function offset_c:longint;static;inline; end; //const // rec_a_field_c_offset=longint(@rec_a(nil^).c); // no known way to make this work {$warnings off} function get_ofs1:longint;inline; var abc:^rec_a; begin result:=longint(@abc.c)-longint(abc); end; {$warnings on} function get_ofs2:longint; asm mov eax,offset rec_a.c end; function get_ofs3:longint;inline; begin result:=longint(@rec_a(nil^).c); end; function get_ofs4:longint;inline; begin result:=longint(@prec_a(nil).c); end; class function rec_a.offset_c:longint; begin result:=longint(@prec_a(nil).c); end; var rec_a_ofs:rec_a; function get_ofs6:longint;inline; begin result:=longint(@rec_a_ofs.c)-longint(@rec_a_ofs); end; procedure TForm1.Button1Click(Sender: TObject); begin showmessage(inttostr(get_ofs1)); showmessage(inttostr(get_ofs2)); showmessage(inttostr(get_ofs3)); showmessage(inttostr(get_ofs4)); showmessage(inttostr(rec_a.offset_c)); showmessage(inttostr(get_ofs6)); // showmessage(inttostr(rec_a_field_c_offset)); end; 解决方法
我总是用这种方法:
Offset := Integer(@rec_a(nil^).c); 不要让使用nil ^把你关掉,这是完全安全的.而不用担心64位指针截断.如果你有一个大小为> 4GB的记录,那么你有更大的问题! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |