2007-1-31 14:17
skyjacker
CnPack Tip#1 如何理解Move
CnPack Tip#1 如何理解Move
Thx: 小峰
[color=#333333][url=http://www.cnpack.org/][font=宋体][size=3][color=#800080]http://www.cnpack.org[/color][/size][/font][/url]
[font=宋体][size=3]CnPack IV QQ Group: 130970
2007-01-31[/size][/font][/color]
Q:
procedure Move(const Source; var Dest; Count: Integer);
问一下这里的参数Source和Dest没有说明数据类型,那具体应该如何使用啊?
var
xx, yy: array [0..6] of Char;
begin
FillChar(xx, 7, #0);
xx := 'abcdef';
Move(xx, yy, 4);
Move(xx[0], yy[0], 4)
//上面这两条语句有什么区别
end;
A:
xx, yy就是一块数据。
xx[0] 就是这块数据的第一个字符
这两个的起始地址相同,因此move的结果也相同了。
测试代码:
procedure TForm1.btnXClick(Sender: TObject);
var
xx, yy: array [0..6] of Char; // 内容存在栈里
a: array of Char; // 内容存在堆里,这就可以理解为什么动态数组a代表的是字符串的指针了
begin
SetLength(a, 10);
FillChar(xx, 7, #0);
xx := 'abcdef';
a[0]:='A';
a[1]:='B';
Move(xx, yy, 4);
Move(xx[0], yy[0], 4);
Move(xx,a[0],4);
end;
注释一下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 //精华1:小心,别覆盖了Source
for I := count-1 downto 0 do
D[I] := S[I]
else
for I := 0 to count-1 do
D[I] := S[I];
end;
{$ELSE}
asm
{ ->EAX Pointer to source }
{ EDX Pointer to destination }
{ ECX Count }
PUSH ESI
PUSH EDI
MOV ESI,EAX
MOV EDI,EDX
MOV EAX,ECX
CMP EDI,ESI
JA @@down
JE @@exit
SAR ECX,2 { copy count DIV 4 dwords }
JS @@exit
REP MOVSD
MOV ECX,EAX //精华2: 放之四海皆准。
AND ECX,03H
REP MOVSB { copy count MOD 4 bytes }
JMP @@exit
@@down:
LEA ESI,[ESI+ECX-4] { point ESI to last dword of source }
LEA EDI,[EDI+ECX-4] { point EDI to last dword of dest }
SAR ECX,2 { copy count DIV 4 dwords }
JS @@exit
STD
REP MOVSD
MOV ECX,EAX
AND ECX,03H { copy count MOD 4 bytes }
ADD ESI,4-1 { point to last byte of rest }
ADD EDI,4-1
REP MOVSB
CLD
@@exit:
POP EDI
POP ESI
end;
{$ENDIF}
注:
Passion:
C/Pascal等高级语言里头的指针其实是一个存储了地址的内存单元,
其存储的内容(是一个地址)所指的地方才是这个指针所指的内容。
而I:Integer只是一个内存单元,I的内容是整型变量,没有地址的说法。
@I才能得到I的地址。
[[i] 本帖最后由 skyjacker 于 2007-1-31 15:50 编辑 [/i]]
2007-2-1 10:34
crystal999
he MoveMemory function moves a block of memory from one location to another.
VOID MoveMemory (
PVOID Destination, // address of move destination
CONST VOID *Source, // address of block to move
DWORD Length // size, in bytes, of block to move
);
Parameters
Destination
Points to the starting address of the destination of the move.
Source
Points to the starting address of the block of memory to move.
Length
Specifies the size, in bytes, of the block of memory to move.
Return Values
This function has no return value.
Remarks
The source and destination blocks may overlap.
如上是系统API
不过delphi直接写得话
procedure MoveMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
begin
Move(Source^, Destination^, Length);
end;
含义就出来了,拷贝内存而已