Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 如何在记录中声明固定值?_Delphi - Fatal编程技术网

Delphi 如何在记录中声明固定值?

Delphi 如何在记录中声明固定值?,delphi,Delphi,我想知道如何声明具有固定值的记录。我需要使用以下模式发送数据:Byte($FF)-Byte(0..250)-Byte(0..250)。我正在使用record,我希望它的第一个值保持不变,这样就不会弄乱它。 例如: Delphi的现代版本允许使用记录方法。虽然无法阻止他人更改字段,但至少可以正确初始化它: type TPacket = record InitByte: byte; // =255, constant FirstVal, SecondVal: byte;

我想知道如何声明具有固定值的记录。我需要使用以下模式发送数据:
Byte($FF)-Byte(0..250)-Byte(0..250)
。我正在使用
record
,我希望它的第一个值保持不变,这样就不会弄乱它。 例如:


Delphi的现代版本允许使用记录方法。虽然无法阻止他人更改字段,但至少可以正确初始化它:

type
  TPacket = record
    InitByte: byte; // =255, constant
    FirstVal,
    SecondVal: byte;
    constructor Create(val1, val2 : byte);
  end;


constructor TPacket.Create(val1, val2: byte);
begin
  InitByte := 255;
  FirstVal := val1;
  SecondVal := val2;
end;

鉴于记录现在可以具有属性,您可以将记录定义为:

TMixedFixed = record
strict private
  FFixed: byte;
  FVariable1: byte;
  FVariable2: byte;
public
  property Fixed read FFixed;
  property Variable read FVariable write FVariable;
  constructor Create(Var1, Var2: byte);
end; 

constructor TMixedFixed.create(Var1, Var2: byte);
begin
  FFixed:= 255;
  FVariable1:= Var1;
  FVariable2:= Var2;  
end;
考虑到实际变量是严格私有的,如果没有特殊的魔法,你不应该接触它们。
您必须使用构造函数初始化“固定”值。

这是最简单的方法:

type
  TPacket = record
    InitByte: byte; // =255, constant
    FirstVal,
    SecondVal: byte;
  end;

var  
  Packet : TPacket = (InitByte: 255);

const
  Packet1 : TPacket = (InitByte: 255);

您不能依赖构造函数,因为与类相反,记录不需要使用它们,默认的无参数构造函数是隐式使用的

但您可以使用常量字段:

type
  TPacket = record
   type
     TBytish = 0..250;
   const
     InitByte : Byte = 255;
   var
     FirstVal,
     SecondVal: TBytish;
  end;
然后将其用作常规记录,除非您没有(并且您不能)更改
InitByte
字段。
FillChar
保留常量字段并按预期运行

procedure TForm2.FormCreate(Sender: TObject);
var
  r: TPacket;
begin
  FillChar(r, SizeOf(r), #0);
  ShowMessage(Format('InitByte = %d, FirstVal = %d, SecondVal = %d', [r.InitByte, r.FirstVal,r.SecondVal]));
  // r.InitByte := 42;  // not allowed by compiler
  // r.FirstVal := 251; // not allowed by compiler
  r.FirstVal := 1;
  r.SecondVal := 2;
  ShowMessage(Format('InitByte = %d, FirstVal = %d, SecondVal = %d', [r.InitByte, r.FirstVal,r.SecondVal]));
end;

更新了以包含嵌套类型范围
0..250

您可以求助于子范围类型如果您所做的只是TPacket中的字节值,我将使用RawByteString,只定义名为InitByte=0、FIrstVal=1的常量,依此类推。我会在PacketBuild函数的代码中确保初始值是正确的常量值。您将使用什么Delphi版本?您所说的“使用此模式发送数据”是什么意思?您是否打算使用TStream.Write(数据包,大小(数据包))或类似工具?如果不是,为什么它必须是一个记录?我将测试一个COM通信,它将通过WriteFile发送,所以字节数组也可能是一种可能性。但我想让它更“整洁”,而record似乎是一个更好的选择,这并不妨碍在不使用构造函数的情况下声明变量并将其用作标准记录。你只会在
ffix
中有垃圾,而且没有办法改变它…@francois,你不能否决默认构造函数吗?我不知道。默认构造函数非常突出,它甚至阻止您声明另一个无参数构造函数。您提供的任何自定义构造函数都需要有参数。请参阅:“记录是自动构造的,使用默认的无参数构造函数,但类必须显式构造。因为记录有默认的无参数构造函数,所以任何用户定义的记录构造函数都必须有一个或多个参数。”不,这不是唯一的方法,请参阅我的答案。而且,顺便说一句,你不能像你的包变量那样初始化局部变量(编译器错误E2195)。@Mike,几乎是。弗朗索瓦,你错过了
FirstVal
SecondVal
的范围保持。如果我做对了,它们应该在
0..250
的范围内。但是你可以用
FillChar
来解决这个问题,它可以设置超出这个界限的值(范围检查肯定是关闭的)。@TLama,我依赖OP的记录声明,错过了范围。使用子类型更新了答案…@TLama,FillChar从不遵循值范围,因为它只是在保留内存中写入任何字节。const声明使FillChar无法访问第一个字段;这几乎是我们所能做的。无法阻止直接进入和戳入内存;-)@TLama,`值:=251;R.FirstVal:=值;`将给您一个范围检查错误(前提是您在编译选项中启用了它),就像您试图潜入的任何其他范围滥用一样。:)是的,但这是一个运行时错误,可能是不需要的,+1:)
procedure TForm2.FormCreate(Sender: TObject);
var
  r: TPacket;
begin
  FillChar(r, SizeOf(r), #0);
  ShowMessage(Format('InitByte = %d, FirstVal = %d, SecondVal = %d', [r.InitByte, r.FirstVal,r.SecondVal]));
  // r.InitByte := 42;  // not allowed by compiler
  // r.FirstVal := 251; // not allowed by compiler
  r.FirstVal := 1;
  r.SecondVal := 2;
  ShowMessage(Format('InitByte = %d, FirstVal = %d, SecondVal = %d', [r.InitByte, r.FirstVal,r.SecondVal]));
end;