读书人

MOVE 操作的疑惑

发布时间: 2012-11-03 10:57:44 作者: rapoo

MOVE 操作的困惑
var
s:string;
ps:Pchar;
b:pbyte;
len:integer;
begin
s:=edit1.Text; //字符串
ps:=pchar(s); //转成pchar类型,
len:=length(s);//取字符串长度,占用多少字节
getmem(b,len);//申请内存,pchar,pbyte在使用前都必须要申请内存,因为他们是指针.
move(ps^,b^,len);//这里 ps^意思是pchar指向内存数据的第一个字节地址,B^是表示申请内存的第一个字节地址,这样就可以一个一个字节的移到b里去了.
memo1.Text:=pchar(b);//显示.
freemem(b);
end;

以上代码中:为什么 move(s,b,len)不行呢? MOVE 的第一、二两个参数到底是传值还是传址。

传址的话,也不对呀,因为MOVE的原型是

procedure Move( const Source; var Dest; count : Integer );
{$IFDEF PUREPASCAL}
var
S, D: PChar;
I: Integer;
begin
S := PChar(@Source);//取内存地址
D := PChar(@Dest);//取内存地址
if S = D then Exit;
if Cardinal(D) > Cardinal(S) then
for I := count-1 downto 0 do
D[I] := S[I]
else
for I := 0 to count-1 do
D[I] := S[I];
end;






[解决办法]
如果传地址,那么下句:
S := PChar(@Source);//取内存
D := PChar(@Dest);//取内存地址

就变成指针的地址了,这样就错了。
[解决办法]
我记得前段时间在网上看到,其实move和copy差不多,只是名字起得。。。。
[解决办法]
首先纠正一下:
getmem(b,len+1);//应当加1,因为字符串以0结尾,而Length函数是没把0计算在内的。
move(ps^,b^,len+1);//复制字符串,包括末尾的0

再解释下Move:
MOVE 的第一、二两个参数是传址的。
比如正确的move(ps^,b^,len+1),在这里,ps指向的是字符串s的第一个字符所在的地址X,b指向的是分配到的内存的首地址Y,所以ps^、b^分别是X、Y,而ps、b则分别表示变量自身的地址。其实这样也是可以的:
Move(PChar(s)^,b^,len+1);
对于不正确的move(s,b,len+1),在这里,s表示变量自身的地址。


注意上面的解释中用到了“在这里”的字眼,因为在不同的语境下,变量名所代表的含义可能有所区别。比如:
自定义函数f1(p: pbyte)和f2(const p),当如下调用时:
f1(b);//此处b表示它指向的地址
f2(b);//此处b表示变量自身的地址
[解决办法]
另外关于MOVE的原型,你注意编译指令{$IFDEF PUREPASCAL},断点调试会发现根本没进去,其实是走到了{$ELSE}分支:
asm
cmp eax, edx
je @@Exit {Source = Dest}
...
end;
{$ENDIF}

读书人网 >.NET

热点推荐