=================本人学识水平有限======望请批评指正===========================
delphi中const i=1 和 const i:integer=1的区别
昨天我们qq群内几个常上线的灌客,接到一位群友的提问:
const i=1和
const i:integer=1 有什么区别?
我最开始以为,这没有什么分别,实际编程中也不见得有什么明显的区别。
因为,这么写法,外在程序实际运行结果都一样。
而事实上,从编译器角度分析和追踪,这两种写法还是有很大的区别的!
我们群的猴哥,最先搞起了试验。声明了两个这样的变量:
const i = $1;
const j: integer = 8;
procedure TForm2.Button1Click(Sender: TObject);
var s: string;
begin s:= inttostr(i);
showmessage(s);
s:=inttostr(j);
showmessage(s);
end;
用调试跟踪器跟踪发现:
mov eax, $00000001---->这是const i=1;
mov exa [$0045b72c]---->这是const j:integer=8;
后改变了i的值,发现第一条 mov eax 后的内容始终也跟着变,也就是静态的保存了直接数值;
而后者则一直是一串地址,也就是真正的开辟了内存地址!
后来又将i=一个浮点数,跟踪结果:
Unit2.pas.33: s:= floattostr(i);
00457F0F 6805400000 push $00004005
00457F14 686666E6F6 push $f6e66666
00457F19 6866666666 push $66666666 ---------〉为了保存这个静态浮点数,将其压入了栈中。
00457F1E 8D45FC lea eax,[ebp-$04]
00457F21 E86A1BFBFF call FloatToStr
Unit2.pas.34: showmessage(s);
00457F26 8B45FC mov eax,[ebp-$04]
00457F29 E84244FDFF call ShowMessage
Unit2.pas.35: s:=inttostr(j);
00457F2E 8D55FC lea edx,[ebp-$04]
00457F31 A12CB74500 mov eax,[$0045b72c]-----〉而后者仍然是存放一个地址!
00457F36 E8A506FBFF call IntToStr
Unit2.pas.36: showmessage(s);
00457F3B 8B45FC mov eax,[ebp-$04]
00457F3E E82D44FDFF call ShowMessage
Unit2.pas.38: end;
00457F43 33C0 xor eax,eax
前一种写法编译器直接将值保存到寄存器,后一种是将常量地址保存到寄存器。
这也是为什么以下这样的程序写法可以更改后者常量的原因:
const a :integer=1;
pn:poniter;
pn:=@a;
integer(pn^):=5; //最后a却等于了5
得出初步结论
const i=1 要比 const i: integer=1 安全一些,因为后者可以在程序运行期间直接修改内存地址的数值从而被破坏者利用。