当参数类型为开放Char数组时,是否允许使用动态Char数组?

发布于 2024-09-24 20:06:36 字数 945 浏览 6 评论 0原文

我正在查看Delphi:Char和TCharArray“不兼容类型”的数组并开始试验。我的发现相当有趣。

procedure Clear(AArray: array of Integer);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := 0;
end;

var
  MyArray: array of Integer;
begin
  Clear(MyArray);
end.

这个简单的小示例展示了如何使用开放数组参数将动态数组传递给过程。它完全按照预期编译和运行。

procedure Clear(AArray: array of Char);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := #0;
end;

var
  MyArray: array of Char;
begin
  Clear(MyArray);
end.

这是几乎相同的代码,唯一的区别是它使用 Char 数组而不是 Integer。它无法编译。相反,编译器会吐出:

 E2010 Incompatible types: 'Array' and 'Dynamic array'

为什么会这样?

经过一段时间的搜索,我发现了这份 QC 报告。我正在运行 Delphi 2009 并且它仍然在发生。

I was looking at Delphi: array of Char and TCharArray "Incompatible Types" and started experimenting. What I discovered is rather interesting.

procedure Clear(AArray: array of Integer);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := 0;
end;

var
  MyArray: array of Integer;
begin
  Clear(MyArray);
end.

This simple little example shows how you can pass a Dynamic Array to a procedure using an Open Array parameter. It compiles and runs exactly as expected.

procedure Clear(AArray: array of Char);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := #0;
end;

var
  MyArray: array of Char;
begin
  Clear(MyArray);
end.

Here is nearly identical code the only difference being it is using an array of Char rather than Integer. It does not compile. Instead the compiler spits out:

 E2010 Incompatible types: 'Array' and 'Dynamic array'

Why would this be?

After searching for a while I discovered this QC report. I'm running Delphi 2009 and its still happening.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浅唱ヾ落雨殇 2024-10-01 20:06:36

由于文档特别提到 Char 类型的开放数组参数与动态数组兼容,因此这应该是一个错误。来自“打开数组参数”

函数 Find(A:Char 数组):
整数;
[...]
注意: [...]
前面的示例创建了一个函数
接受任何 Char 元素数组,
包括(但不限于)动态
数组。 [...]

Since the documentation specifically mentions open array parameters of type Char to be compatible with dynamic arrays, this should be a bug. From 'Open Array Parameters':

function Find(A: array of Char):
Integer;
[...]
Note: [...] The
previous example creates a function
that takes any array of Char elements,
including (but not limited to) dynamic
arrays. [...]

喜爱皱眉﹌ 2024-10-01 20:06:36

您可以使用这种数组,定义您自己的类型:

type
  TCharDynArray = array of char;

procedure Clear(AArray: TCharDynArray);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := #0;
end;

procedure test;
var
  MyArray: TCharDynArray;
begin
  Clear(MyArray);
end;

此代码可以正常编译。当然它没有做任何有用的事情(AArray 参数没有设置为“var”,因此在为每个项目分配 #0 之前将其复制到堆栈上)。但至少,它可以编译。

在实践中,我发现动态数组(如 TIntegerDynArray)更容易定义或使用高级类型,因为至少它允许您使用 var 将数组作为引用传递,从而避免在堆栈上进行复制,并使您的代码更快。

关于映射到 PChar,这对于所有动态数组都是常见的:您可以将 TIntegerDynArray 映射到指针,然后将其用作 PInteger 或 PIntegerArray:

procedure AddInteger(var Values: TIntegerDynArray; Value: integer);
var n: integer;
begin
  n := Length(Values);
  SetLength(Values,n+1);
  Values[n] := Value;
end;

procedure Loop(V: PInteger);
begin
  if V<>nil then
    while V^<>0 do begin
      write(V^,' ');
      inc(V); // go to next integer in array
    end;
end;

var IntArray: TIntegerDynArray;
begin
  Loop(pointer(IntArray)); // will display nothing, since pointer(IntArray)=nil for IntArray=[]
  AddInteger(IntArray,2);
  AddInteger(IntArray,3);
  AddInteger(IntArray,0);
  Loop(pointer(IntArray)); // will display '2 3 '  
end.

问题是“char 数组”代码与“整数数组”不一致" 当然是在编译器内在函数中,而且 PChar 可以类型转换为字符串。

You can work with this kind of array, defining your own type:

type
  TCharDynArray = array of char;

procedure Clear(AArray: TCharDynArray);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := #0;
end;

procedure test;
var
  MyArray: TCharDynArray;
begin
  Clear(MyArray);
end;

This code will compile fine. It doesn't do anything useful of course (the AArray parameter is not set as "var", so it's copied on the stack before assigning a #0 to every item). But at least, it compiles.

In practice, I found out more easy to define or use high-level of types for dynamic arrays (like TIntegerDynArray), because at least it allows you to pass the array as reference, using a var, therefore avoiding to make a copy on stack, and make your code faster.

About the mapping to a PChar, it's usual for all dynamic arrays: you can map a TIntegerDynArray to a pointer, then use it as a PInteger or a PIntegerArray:

procedure AddInteger(var Values: TIntegerDynArray; Value: integer);
var n: integer;
begin
  n := Length(Values);
  SetLength(Values,n+1);
  Values[n] := Value;
end;

procedure Loop(V: PInteger);
begin
  if V<>nil then
    while V^<>0 do begin
      write(V^,' ');
      inc(V); // go to next integer in array
    end;
end;

var IntArray: TIntegerDynArray;
begin
  Loop(pointer(IntArray)); // will display nothing, since pointer(IntArray)=nil for IntArray=[]
  AddInteger(IntArray,2);
  AddInteger(IntArray,3);
  AddInteger(IntArray,0);
  Loop(pointer(IntArray)); // will display '2 3 '  
end.

The problem is the "array of char" code beeing inconsistent with "array of integer" is certainly in compiler intrinsics, and the fact that a PChar can be type-casted to a string.

蝶…霜飞 2024-10-01 20:06:36

我认为原因是 char 数组PChar 兼容,因为此代码确实可以编译:

procedure Clear(AArray: array of Char);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := #0;
end;

var
  MyArray: array of Char;
  P: PChar;
begin
  Clear(P^);
end.

这可能是出于历史原因。

希望巴里·凯利丹尼·索普将介入并提供更多反馈。

——杰罗恩

I think the reason is that array of Char is compatible with PChar, as this code does compile:

procedure Clear(AArray: array of Char);
var
  I: Integer;
begin
  for I := Low(AArray) to High(AArray) do
    AArray[I] := #0;
end;

var
  MyArray: array of Char;
  P: PChar;
begin
  Clear(P^);
end.

That is probably for historic reasons.
Hopefully Barry Kelly or Danny Thorpe will kick in and provide some more feedback on this.

--jeroen

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文