我认为,这是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给你的规则了。