请问Int64Rec(FSize).Lo := 1为何无法通过编译?(50分)

  • 主题发起人 主题发起人 ow
  • 开始时间 开始时间
O

ow

Unregistered / Unconfirmed
GUEST, unregistred user!
var
FSize: Int64;
begin
Int64Rec(FSize).Lo := 1;
end;

为何以上语句会导致编译错误:Left side cannot be assigned to
 
在我的机器上很好呀,没有错误(WinXp+Delphi6-6.163)
 
没错啊!
WIN2000 + DELPHI5
 
不好意思,原来的代码是这样的:

TTest = class(TObject)
private
FSize: Int64;
public
procedure SetSize;
end;

procedure TTest.SetSize;
begin
Int64Rec(FSize).Lo := 1
// 编译出错
end;
 
用一个天下第一傻方法:
TTest = class(TObject)
private
FSize: Int64;
public
procedure SetSize;
end;

procedure TTest.SetSize;
var ASize : Int64;
begin
Int64Rec(ASize).Lo := 1

FSize := ASize;
end;
 
嘻嘻,不好意思,居然贴出这么傻的办法,我来改一下:
type
TTest = class(TObject)
private
FSize: Int64;
public
procedure SetSize;
end;
PIR = ^Int64Rec


procedure TTest.SetSize;
begin
PIR(@FSize).Lo :=1;
end;

 
我认为,这是BORLAND的一个BUG,当然BORLAND的程序员未必如此认为,我记得以前
问过一个问题,最后得到的答案是by design

这是如何引起来的呢?
BUG是对变量以及类成员的强制结构的非同等对待引起的。

DELPHI将变量翻译成为 [EBP-X] ,而类成员则被翻译成为[EBX+X],EBX是实例的基地址,
就是SELF

在对[EBP-X]的强制结构的操作中,直接使用了原来的[EBP-X]来访问
而对[EBX+X]的强制结构的操作中,采用了类似于C语言的INLINE函数的处理(就是宏)
翻译成为了 MOV EAX,[EBX+X]
MOV [EBP-XX],EAX
MOV EAX,[EBX+X+4]
MOV [EBP-XX+4],EAX
以后,然后再使用[EBP-XX]来替代[EBX+X]访问

打个比方,本来我们是要 INT64REC(ASIZE):=INT64REC(FSIZE);
//其中,ASIZE=[EBP+4],FSIZE=[EBX+1000]
他会翻译成为
MOV EAX,[EBX+1000] //ASSERT FSIZE OFFSET IS 1000
MOV [EBP-10],EAX
MOV EAX,[EBX+1004]
MOV [EBP-0C],EAX

MOV EAX,[EBP-10]
MOV [EBP-8],EAX
MOV EAX,[EBP-0C]
MOV [EBP-4],EAX
我们可以知道,他竟然先将FSIZE放入了临时的栈中,然后再来使用

也就是说INT64REC(FSIZE)在DELPHI的眼里,成了[EBP-10] !!!!
在这样的情况下,无论你使用的是INT64REC(FSIZE).LO:=1;
还是 INT64REC(FSIZE):=INT64REC(ASIZE);
都会出现一个左边不可以被赋值!!!

为什么呢?左边只是一个临时的堆变量而已,就象我们在执行

PROCEDURE SETFSIZE(SIZE:INT64);
BEGIN
SIZE:=1

END;
在执行SETFSIZE的时候,无论里面如何修改SIZE,外面的FSIZE都不会为之所动

而INT64REC(FSIZE)就象是在执行一个这样的INLINE SETFSIZE(INLINE就是MACRO,不需要CALL)

这个也属于BY DESIGN么?谁会知道INT64REC(FSIZE)竟然会做这么多事情?成了一个临时
栈变量?不可修改?
而INT64REC(ASIZE)却不会?
到底是那破DELPHI设计者脑袋有问题还是我们这些CODER们脑袋进水了?

BTW:
其实DELPHI类似二义还有很多。
我个人写的程序往往比较难看,例如一个PCHAR(STR)我往往会写成PCHAR(@STR[1])
不是我脑袋有问题,只是当你发现 STRING(PCHAR)和STRING(POINTER)的区别之后,你就不再相信
自己的脑袋,也不再相信DELPHI给你的规则了。
 
后退
顶部