动态数组,从C ++转换为Delphi

时间:2014-04-22 19:35:12

标签: c++ delphi

我不明白为什么Delphi不像C ++那样工作

float *buffer;
buffer=new float[2];
buffer[0]=0.1;
buffer[1]=0.2;
buffer+=1;
//now buffer[0] has value of buffer[1] and buffer[1] has value 0

德尔福代码:

buffer: array of Single;
SetLength(buffer,2);
buffer[0]:=0.1;
buffer[1]:=0.2;
buffer:=buffer+1; //doesn't work

2 个答案:

答案 0 :(得分:8)

您展示的Delphi代码并不是C ++代码所做的等效翻译 - 利用指针算法。以下是更接近的翻译:

如果您使用的是D2009 +:

{$POINTERMATH ON}

var
  buffer: PSingle;

GetMem(buffer, SizeOf(Single) * 2);
buffer[0] := 0.1;
buffer[1] := 0.2;
buffer := buffer + 1;

如果您使用的是D2007或更早版本,请使用更像这样的内容:

type
  TSingleArray = packed array[0..(MaxInt div SizeOf(Single))-1] of Single;
  PSingleArray = ^TSingleArray;

var
  buffer: PSingle;

GetMem(buffer, SizeOf(Single) * 2);
PSingleArray(buffer)^[0] := 0.1;
PSingleArray(buffer)^[1] := 0.2;
Inc(buffer);

答案 1 :(得分:7)

您收到的很多评论正在发生,因为您的C ++代码是荒谬的,人们不明白为什么要这样做,在C ++或Delphi中。

指针指向内存地址,通常假定它包含一个变量。但在C(和C ++和类似语言)中,指针也用作数组;而不是一个明确定义的“数组类型”,你只需要一个指向第一个元素和数组语法的指针。你的buffer+=1行基本上意味着“将指针移动到它当前所在的变量元素之后。”你声称now buffer[0] has value of buffer[1] and buffer[1] has value 0,但它并不那么简单。旧缓冲区[0]没有去任何地方;你刚刚移动指针。

你来自:

  | 
  V
-----------------
| 0 | 1 | beyond|
-----------------
|0.1|0.2|???????|
-----------------

为:

      | 
      V
-----------------
| 0 | 1 | beyond|
-----------------
|0.1|0.2|???????|
-----------------

现在看起来缓冲区[0]已经改变了它的值,但是值没有改变;你刚刚移动指针。

我将数组结束后的值保留为标记为?s的原因。那不是真的0;这是未定义的,它包含在这些字节的内存中发生的任何事情。现在可能是0,但是如果你再次运行它(或者在不同的地方运行它)电脑)你可以轻松得到一些随机数。 “未定义的行为”是程序员所说的“以不可预测和难以追踪的方式出现问题”。这不是一件好事。 C充满了它;德尔福,更不用说了。

你想要做的事情在Delphi中不起作用的原因是Delphi有明确定义的数组类型与指针完全不同。动态数组可能看起来像“只是一个数组”,但它实际上是一个包含有关数组元数据的数据结构,并在其末尾粘贴了一个数组。所以你不能移动指针;没有“元素指针”与C代码的方式。

如果你真的想得到一个指向数组中元素的指针,也许是因为你一次扫描一个元素,你可以声明一个指针类型的变量(使用^运算符)并使用@运算符进行设置,如下所示:

var
buffer: array of Single;
ptr: ^single;
begin
   SetLength(buffer,2);
   buffer[0]:=0.1;
   buffer[1]:=0.2;
   ptr := @buffer[1];
end;

但同样,指针不是数组,数组不是指针。所以你不能说ptr[0]。 (一些指针类型,例如PChar,由于它们代表C API字符串,因此它们代表C API字符串,因此它们代表C API字符串,因此该规则会例外,因为它们不应该像数组那样处理指针。)

如果您想要做的是扫描数组,那么有更好的方法。因为数组类型定义良好且Delphi知道它有多长,所以你可以这样做:

for value in buffer do
   //do whatever

这称为枚举器,它作为一种特殊的for循环,循环遍历数组中的每个元素,并将其提供给索引变量。

我希望这会有所帮助。如果没有,请澄清您正在尝试使用此代码,我会尝试更好地解释。 :)