delphi - 如何在const记录中使用declare和指向const数组的指针?

时间:2009-10-07 08:58:22

标签: delphi arrays pointers

我有一些相同基类型但大小不同的const数组,我需要在const记录中指向它们。下面的代码编译成功,但完成时出错。

type
  Toffsets = array of integer;

  Trec = record
             point1: Tpoint;          //complete size
             point2: Tpoint;
             aOffsets:  ^Toffsets;
           end;

const
  cOffsetsA: array [0..3] of integer = (7, 4, 2, 9);
  cOffsetsB: array [0..5] of integer = (1, 2, 3, 4, 5, 6);

  cRec1: Trec = (
    point1:   (x: 140; y: 46);
    point2:   (x: 5; y: 7);
    aOffsets: @cOffsetsA;
  );

  cRec2: Trec = (
    point1:   (x: 40; y: 6);
    point2:   (x: 5; y: 7);
    aOffsets: @cOffsetsB;
  );

在我的代码中,我需要从具有指向记录的指针的cOffsetsA / B数组访问数据。我试着这样做:

var pMyRec: ^Trec;
...
pMyRec := @cRec1;
...
i := pMyRec^.aOffsets^[0];

这导致错误 - '访问违规...读取地址000000 ......'

任何人都可以在这里解释错误以及如何解决,应该怎么做?

我可能还需要在记录中添加_length字段,它将保存指针所指向的数组的大小;这不是问题。

祝你好运, LUK

3 个答案:

答案 0 :(得分:1)

虽然在Delphi中使用这样的常量是可以的,但我只想补充一点,以这种方式做事通常不是一个好主意。就个人而言,如果这个代码在某个单元中,我会使用这样的东西:(D2007及更高版本)

type
  Toffsets = array of integer;
  Trec = record
    point1: Tpoint; //complete size
    point2: Tpoint;
    aOffsets: ^Toffsets;
    constructor Create(X1, Y1, X2, Y2: Integer; Offsets: array of integer);
  end;

因此,记录获得一个构造函数,它将用适当的数据填充它。作为缺点,如果要使用构造函数来填充数据,则不能再将其声明为const。但是,您可以使用“初始化”部分中的以下代码来解决此问题:

var
  cRec1: Trec;

initialization
  cRec1 := Trec.Create(140, 6, 5, 7, cOffsetsA);

此代码将记录声明为全局变量而不是常量,并将其填入您的数据。

您的构造函数可能如下所示:

constructor Trec.Create(X1, Y1, X2, Y2: Integer; Offsets: array of integer);
var
  I: Integer;
begin
  point1.X := X1;
  point1.Y := Y1;
  point2.X := X2;
  point2.Y := Y2;
  new(aOffsets);
  SetLength(aOffsets^, 0);
  for I in Offsets do
  begin
    SetLength(aOffsets^, Succ(Length(aOffsets^)));
    aOffsets^[Pred(Length(aOffsets^))] := I;
  end;
end;

这将填写您的数据记录。但是,您不必使用构造函数以这种方式创建记录!这只是一个附加功能。

为了使它更有趣,您可以为两个点和数组添加属性,使字段本身为私有,并且仅声明属性的读取方法。这样,您仍然可以确保其内容是只读的并保持只读。

但使用代码的风险是什么?好吧,因为你将它们全部声明为常量,所以风险不大,除非你允许可分配的类型常量。 ({$ J +}被声明...)在这种情况下,一段代码可以更改cOffsetsA中的值,它也会在cRec1中更改。那是你要的吗?

无论如何,通过使用构造函数并在代码中初始化它们,可以使代码更具动态性。但是,它仍然保持简单的记录类型,其他属性和方法不会改变它的结构或大小。

你需要Delphi 2007或更高版本,但是......

答案 1 :(得分:0)

看起来我自己找到了答案:

type
  Toffsets = array of integer;

是动态数组类型,setLength必须与此类型的任何变量一起使用才能分配内存。我需要的是一个指向现有常量数组的指针,因此为了解决这个问题,唯一必须改变的就是声明这种类型。它应该看起来像:

type
  Toffsets = array [0..0] of integer;

是的,我必须将记录中的_length字段添加为低(pMyRec ^ .aOffsets ^),高(...)和长度(...)不起作用。

祝你好运, LUK

答案 2 :(得分:0)

以下应该有效:


i:=TOffsets(pMyRec^.aOffsets)[0];