由 FillChar所引起的思考。。。。。。 ( 积分: 0 )

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

xingkong97

Unregistered / Unconfirmed
GUEST, unregistred user!
FillChar函数我想很多人都会用了,这里我想再说一下。
首先说一下常碰到的问题。
例如:定义:A : array[0..9] of integer;
然后这样做:FillChar(A,sizeof(A),0);一些OK,没有错误。
再定义:A : array of integer;
然后这样做:SetLength(A,10);FillChar(A,sizeof(A),0);showmessage(inttostr(A[0]));出现错误。
这里的错误有两个:
第一是sizeof(A),为什么呢?因为这里的A在定义的时候定义为动态数组,因此sizeof(A)会在定义处找A的大小,发现A为integer类型,当然就为4个字节了,所以sizeof(A)=4,但是我们为它实际上分配了40个字节,错误;
第二是以A为参数,这是为什么呢,有人会说在第一个例子中并没错啊。这里的原因还是因为A定义为了动态数组。如果不定义为动态数组,例如:A : array[0..9] of integer,那么这里的A在这里指的就是A[0],我们可以通过下面的程序得到验证:
定义:A:array[0..9] of integer;
程序:A[0]:=1;
ShowMessage(inttostr(A[0]));ShowMessage(inttostr(integer((@A)^)));
在这里我们通过(@A)^得到A指向的值。
Showmessage(inttostr(integer(A[0])));ShowMessage(inttostr(integer(A)));
我们可以发现A[0]的地址与A的地址一样。即:@A=@A[0]。
但是如果我们定义为动态数组就不一样了,在动态数组 A:array of integer 中,我们执行语句为其设置大小:SetLength(A,10),这时A就不再指向A[0]了,A指向A[0]的地址,
即A=@A[0],我们也可以通过程序进行验证:
定义:A : array of integer;
程序:SetLength(A,10);
A[0]:=123;
ShowMessage(inttostr(Integer(pointer((@A)^)^)));
这里的(@A)^为A中指向的地址即@A[0],然后pointer((@A)^)^找出A[0]单元的内容。
可以发现A确实是指向A[0]的地址的。
那么FillChar(A,sizeof(integer)*10,0)对吗?不对的。在这里FillChar的作用是从A[0]地址开始对连续内存块的每个字节赋0值,但是看看FillChar的内容便知:
var
I: Integer;
P: PChar;
begin
P := PChar(@Dest);
for I := count-1 downto 0 do
P := Value;
end;
可以看到P是指向Dest地址的,因此这里FillChar(A,sizeof(integer)*10,0)就会出现严重的逻辑错误,A是指向数组首地址的,而@A指的是什么呢,显然数组的地址的地址,对其赋值其内容也就不再指向原先数组的头地址了,而是别的地址(严重的错误啊),因此再ShowMessage(A[0]),就会出现错误,因为已经找不到A的地址了。
说到这里,大家应该就知道了,可以改为:FillChar(@A[0],sizeof(integer)*10,0);
当然我这里是拿integer类型作的例子,别的其实也都一样。
好了,一下写了这么多,希望对大家有用。
 
自己顶一下!
 
定义:A : array[0..9] of integer;
这A 是在栈中分配的内存
A : array of integer;
如果是动态树组就可能是在堆中分配内存!
所以@A[0] 地址才是指向目的地址

不知道这样的理解对不对!
 
嗯!!应该是这样的。
 
array[0..9] of integer;是静态内存的首地址
而A : array of integer;是指向这块内存的指针的地址.....
 
感谢楼主的奉献精神!
 
呵呵。。。。。。谢谢啊,以后有什么心得还要写出来,虽然写不太好,但是我坚信通过我们的努力,把delphi的一些细节多写出来,这样多少会弥补一下delphi文档。我坚信一定会有更多的人认识到delphi的魅力的,去更好的用delphi的,我希望这不是我的一相情愿。
 
接受答案了.
 
后退
顶部