Delphi 未公开的语法!!(高手请入) ( 积分: 100 )

  • 主题发起人 主题发起人 xnewmoon
  • 开始时间 开始时间
X

xnewmoon

Unregistered / Unconfirmed
GUEST, unregistred user!
function CheckSum(Var Buffer;
Size : integer) : Word;
type
TWordArray = Array[0..1] of Word;
var
ChkSum : LongWord;
i : Integer;
begin
ChkSum := 0;
i := 0;
While Size > 1do
begin
ChkSum := ChkSum + TWordArray(Buffer);
inc(i);
Size := Size - SizeOf(Word);
end;

if Size=1 then
ChkSum := ChkSum + Byte(TWordArray(Buffer));
ChkSum := (ChkSum shr 16) + (ChkSum and $FFFF);
ChkSum := ChkSum + (Chksum shr 16);
Result := Word(ChkSum);
end;

TWordArray = Array[0..1] of Word;
TwordArray 定义为两个Word型数组,因此其下标不能大于 1 。
但是在CheckSum这个函数中却可以大于1,本人经过调试发现在下标大于1的情况下,也没有报越界错误(我在工程 =》选项=》Compiler=》Range Checking 已选中)。
请高手明示。
 
function CheckSum(Var Buffer;
Size : integer) : Word;
type
TWordArray = Array[0..1] of Word;
var
ChkSum : LongWord;
i : Integer;
begin
ChkSum := 0;
i := 0;
While Size > 1do
begin
ChkSum := ChkSum + TWordArray(Buffer);
inc(i);
Size := Size - SizeOf(Word);
end;

if Size=1 then
ChkSum := ChkSum + Byte(TWordArray(Buffer));
ChkSum := (ChkSum shr 16) + (ChkSum and $FFFF);
ChkSum := ChkSum + (Chksum shr 16);
Result := Word(ChkSum);
end;

TWordArray = Array[0..1] of Word;
TwordArray 定义为两个Word型数组,因此其下标不能大于 1 。
但是在CheckSum这个函数中却可以大于1,本人经过调试发现在下标大于1的情况下,也没有报越界错误(我在工程 =》选项=》Compiler=》Range Checking 已选中)。
请高手明示。
 
这叫什么未公开的语法???[:D]
如果你用过Delphi4以前的版本,那么就不会对这种语法感到困惑。
type
PIntegerArray = ^TIntegerArray;
TIntegerArray = array[0..0] of Integer;
类似这样子的定义一个整型数组类型(指针)用来实现长度未知的动态数组,但需要通过变量来进行索引访问数组因素。象
var P: PIntegerArray;
那么P[0]是可以的,但P[1],P[10]是不可以的,不过I := 10;
P这样访问又是可以的。
 
因为是指针,它通过地址访问,所以有地址的就可以;
 
To:lichengbin
type
PIntegerArray = ^TIntegerArray;
TIntegerArray = array[0..0] of Integer;
类似这样子的定义一个整型数组类型(指针)用来实现长度未知的动态数组。。。。
诚然, 象上面可以实现模拟现在的动态数组, 但TWordArray = Array[0..1] of Word
它是 从0..1 而不是0..0, 你是不是把它们混为一潭了???
 
0..1和0..0有很大的区别吗?只不过是数组上下界范围的不同罢啦。
是不是那么回事,你把 TWordArray(Buffer) 改成 TWordArray(Buffer)[2] 试试看结果如何[:D]
 
汗。。感情被欺骗
Range Checking只是编译时检测,运行时的越界检测不了,所以就像lichengbin说的,指定了下标如果越界能够被编译器报错而像你程序里使用变量做下标就被当作没错咯~
 
To:lichengbin
0..1和0..0有很大的区别吗?只不过是数组上下界范围的不同罢啦???。。。
你如果把下标 该为
type
TWordArray = Array[0..2] of Word;
则在运行中报错(越界错误,不管你 在 工程 =》选项=》Compiler=》Range Checking
选不选中, 都报错), 你可以试一试,
好象只有 TWordArray = Array[0..0] of Word;
或 TWordArray = Array[0..1] of Word;
他是不检查越界的。
 
xnewmoon,又谬矣!越界检查只会在编译器进行编译时才会做的,运行时哪有什么检查越界不越界的说法?只有你访问的内存地址是否允许被访问读写的问题。对于变量索引,编译时编译器不能确定或者说它不敢断定是否越界,所以对于变量或者包含变量的表达式作为索引的情况,一律编译通过的。而运行时是否真的越界,那要看你索引访问的数组元素是否是可访问的数据。
TWordArray = Array[0..2] of Word;
照样可以工作得好好的。
我再给你举个例子,你自己运行测试一下看看。
type
TMyRec = record
A: array[0..2] of Integer;
B: Integer;
C: Integer;
end;

procedure TForm1.Button11Click(Sender: TObject);
var
P: TMyRec;
I: Integer;
begin
for I := 0 to 4do
P.A := I;
Memo1.Lines.Add(Format('P.A[0]: %d', [P.A[0]]));
Memo1.Lines.Add(Format('P.A[1]: %d', [P.A[1]]));
Memo1.Lines.Add(Format('P.A[2]: %d', [P.A[2]]));
Memo1.Lines.Add(Format('P.B: %d', [P.B]));
Memo1.Lines.Add(Format('P.C: %d', [P.C]));
Memo1.Lines.Add('');
for I := 0 to 4do
Memo1.Lines.Add(Format('P.A[%d]: %d', [I, P.A]));
end;
 
不好意思楼主,TWordArray = Array[0..2] of Word;同样[red]不会[/red]在编译时报错,我把range checking和overflow checking都打开了
 
TO:lichengbin
不知道, 你调试CheckSum函数没有???
我经过调试才作出上述回答,绝飞空穴来风。也许你调试那个函数后, 回答就可能有所不同了。
 
To:lichengbin,
for I := 0 to 4do
该为5, for I := 0 to 5do
。。。还回不报错吗???
那是因为 TMyRec 5个integer 大小的缘故!
procedure TForm2.Button1Click(Sender: TObject);
var
P: TMyRec;
I: Integer;
begin
for I := 0 to [red]5[/red]do
P.A := I;
Memo1.Lines.Add(Format('P.A[0]: %d', [P.A[0]]));
Memo1.Lines.Add(Format('P.A[1]: %d', [P.A[1]]));
Memo1.Lines.Add(Format('P.A[2]: %d', [P.A[2]]));
Memo1.Lines.Add(Format('P.B: %d', [P.B]));
Memo1.Lines.Add(Format('P.C: %d', [P.C]));
Memo1.Lines.Add('');
for I := 0 to 4do
Memo1.Lines.Add(Format('P.A[%d]: %d', [I, P.A]));
end;
 
To:lichengbin
xnewmoon,又谬矣!越界检查只会在编译器进行编译时才会做的..???
以下是Delphi 帮助!应该不会错吧!
Delphi compiler options correspond to switch directives that you can also set directly in your program code.
Selecting an option is equivalent to setting the switch directive to its positive (+) state.
Code generation Effect
Optimization Enables compiler optimizations. Corresponds to {$O}.
Stack frames Forces compiler to generate stack frames on all procedures and functions. Corresponds to {$W}.
Pentium-safe FDIV Delphi only. Generates Delphi code that detects a faulty floating-point division instruction. Corresponds to {$U}.
Record field alignment Aligns elements in structures to the specified number of bytes (1, 2, 4, or 8). Choose the alignment type from the drop-down list. Corresponds to {$A}. Note: In older versions of Delphi, this option could be checked on or off. Choosing 1 is the equivalent of off and 8 is the equivalent of on.
[red]Runtime errors Effect
Range checking Checks that array and string subscripts are within bounds. Corresponds to {$R}.[/red]
I/O checking Checks for I/O errors after every I/O call. Corresponds to {$I}.
Overflow checking Checks overflow for integer operations. Corresponds to {$Q}.
 
TWordArray(Buffer);
你用I编译器不知道I是多少当然不会报错了.运行时候I超过了下界才报错.
TWordArray(Buffer)[100];
你给定一个常数在看看,编译器一定会报错的
 
To wr960204:
TWordArray(Buffer);
你用I编译器不知道I是多少当然不会报错了.运行时候I超过了下界才报错.
TWordArray(Buffer)[100];
你给定一个常数在看看,编译器一定会报错的
如果 TWordArray = Array[0..1] of Word 的话,
在运行时, 就是I > 1 是也不会报错。
如果 TWordArray = Array[0..2] of Word 的话, 或把改的更大,则会象你说的那样!
唯一特殊的情况就是:
1。TWordArray = Array[0..1] of Word
2。TWordArray = Array[0..0] of Word 模拟动态数据(以前的用法)
不知道谁能给第 一种情况 一个合理的说法!???
 
[:I]看错了,你一直是在Range checking开关打开,{$R+}选项下测试的。而偶没把它勾上。运行时越界检查,是编译器自动加入了检查代码。这一点,我前面所说的确不对。[:)]
不过,调试了一下,{$R+}选项下,你的CheckSum函数也一样会弹出越界错误,不管是0..0,0..1还是0..2。改变选项后,需要重新Build一下,再Run。
如,0..1,ChkSum := ChkSum + TWordArray(Buffer)生成如下汇编代码:
83FE01 cmp esi,$01 // esi即i的值,与1进行比较
7605 jbe +$05 // <=1,相对跳过5字节,-> movzx
E83F25E5FF call @BoundErr // 抛出越界异常
0FB71C70 movzx ebx,[eax+esi*2]
03CB add ecx,ebx
 
Thank you ! I See!
 
unit Unit1;
{$R+}
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
a: array[0..2] of Word;
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
I: Word;
begin
for I := 0 to 5do
a := I * 2;
end;

end.

这个程序应该和你所说的思路一样吧,按你说的应该会报错是吧~所有检测我都开了,可是重编译并运行只有运行时错误,不知道你为什么0..0,0..1不报错而0..2会。。
 
后退
顶部