我有一些相同基类型但大小不同的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
答案 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];