前一段业余移植一个C写的 Total Commander 插件到 Double Commander, 后者是用FreePascal写的,虽然也可以直接用C来做这个插件,但俺还是有兴趣用freepascal重写一遍。最开始是用Lazarus 做IDE来写,为偷懒基本上是C函数到pascal函数来移,结构打算后面再调整,但移植完两个函数后调测时觉得Lazarus 这个IDE的调试功能实在太差,于是又改到先用Delphi 7来编译,于是发现了这两者在数组、指针方面的一些差异。刚才在Delphi 7, Delphi 2009和Freepascal 2.2.4上做了一下对比,结果如下:
Delphi 7
procedure TestIntArray;
var
arr : array[0..10] of integer;
p : PInteger;
i : integer;
s: string;
begin
for i:=0 to Length(arr)-1 do
arr[i] := i + 1000;
// p := arr; //error: Incompatible types: 'Array' and 'PInteger'
p := @arr;
Writeln(IntToStr(p^));
p := @arr[0]; //the same effect with above line?
Writeln(IntToStr(p^));
// Writeln(IntToStr(p[2])); //error: Array type required
// p := p + 1; //error: Operator not applicable to this operand type
Inc(p);
// Writeln(IntToStr((p+1)^)); //error: Operator not applicable to this operand type
Writeln(IntToStr(p^));
Readln(s);
end;
可以看出
* 不能象C语言那样直接将数组赋值给指针 ( p := arr ),只能 ( p := @arr 或者 p := @arr[0] ),同样 p[2]也不是一个合法的表达式(错误信息为Array type required) * 指针不能直接与数字做运算,比如p + 1这是不合法的(错误信息是Operator not applicable to this operand type),只能inc(p)或者dec(p),如果要增2就inc(p, 2)
但字符数组是个例外:
procedure TestCharArray;
var
arr : array[0..10] of Char;
p : PChar;
i : integer;
s: string;
begin
for i:=0 to Length(arr)-1 do
arr[i] := Chr(Ord('a') + i);
p := arr; //OK!
p := @arr;
Writeln(p^);
p := @arr[0]; //the same effect with above line?
Writeln(p^);
p := p + 1; //OK!
Inc(p);
Writeln(p[2]); //OK!
Writeln((p+1)^); //OK!
Readln(s);
end;
这里,p := arr, p:= p + 2, p[2] 这几个表达式都合法了,并且结果与期望一致。
FreePascal (2.2.4)
procedure TForm1.TestIntArray;
var
arr : array[0..10] of integer;
p : PInteger;
i : integer;
s: string;
begin
for i:=0 to Length(arr)-1 do
arr[i] := i + 1000;
p := arr; //OK!
Memo1.Lines.Add(IntToStr(p^)); //output: 1000
p := @arr;
Memo1.Lines.Add(IntToStr(p^)); //output: 1000
p := @arr[0]; //OK!
Memo1.Lines.Add(IntToStr(p^)); //output: 1000
Memo1.Lines.Add(IntToStr(p[2])); //OK! output: 1002
p := p + 1; //OK!
Inc(p);
Memo1.Lines.Add(IntToStr((p+1)^)); //OK! //output: 1003
Memo1.Lines.Add(IntToStr(p^));
// Readln(s);
end;
即使对于整数数组(其它也是,包括字符串数组),p := arr, p:= p + 2, p[2] 这几个表达式也都是合法的。
Delphi 2009
在默认的选项下,Delphi 2009与Delphi 7相同,上述三种表达式都不支持。但可以打开一个编译选项$POINTERMATH:
{$POINTERMATH ON}
procedure TestIntArray;
var
arr : array[0..10] of integer;
p : PInteger;
i : integer;
s: string;
begin
for i:=0 to Length(arr)-1 do
arr[i] := i + 1000;
// p := arr; //error: Incompatible types: 'Array' and 'PInteger'
p := @arr;
Writeln(IntToStr(p^));{$POINTERMATH ON}
procedure TestIntArray;
var
arr : array[0..10] of integer;
p : PInteger;
i : integer;
s: string;
begin
for i:=0 to Length(arr)-1 do
arr[i] := i + 1000;
// p := arr; //error: Incompatible types: 'Array' and 'PInteger'
p := @arr;
Writeln(IntToStr(p^));
p := @arr[0]; //the same effect with above line?
Writeln(IntToStr(p^));
Writeln(IntToStr(p[2])); //OK in D2009
p := p + 1; //OK in D2009
Inc(p);
Writeln(IntToStr((p+1)^)); //OK in D2009
// Writeln(IntToStr(p^));
Readln(s);
end;
p := @arr[0]; //the same effect with above line?
Writeln(IntToStr(p^));
Writeln(IntToStr(p[2])); //OK in D2009
p := p + 1; //OK in D2009
Inc(p);
Writeln(IntToStr((p+1)^)); //OK in D2009
// Writeln(IntToStr(p^));
Readln(s);
end;
p := arr仍然是不合法的表达式,但 p + 2 和 p[2] 都可以了。
|
请发表评论