首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

MOVE 操作的疑惑

2012-11-03 
MOVE 操作的困惑vars:stringps:Pcharb:pbytelen:integerbegins:edit1.Text //字符串ps:pchar(s) /

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}

热点排行