File 这个Delphi PAnsiChar代码是什么意思?

File 这个Delphi PAnsiChar代码是什么意思?,file,delphi,byte,File,Delphi,Byte,我们都在一个项目中使用Delphi,并且已经使用了多年。 但我们从未见过以下语法与泛七线谱一起使用,也不知道它的意思: buffer : PAnsiChar recInstance : Byte recX : smallint num_info : integer // buffer loaded from a file... num_info := 0; // next two lines are a mystery recInstance := By

我们都在一个项目中使用Delphi,并且已经使用了多年。 但我们从未见过以下语法与泛七线谱一起使用,也不知道它的意思:

buffer       : PAnsiChar
recInstance  : Byte
recX         : smallint
num_info     : integer

// buffer loaded from a file...

num_info := 0;
// next two lines are a mystery
recInstance := Byte(buffer[num_info*5]);
recX := Byte(buffer[num_info*5+1])+256*Byte(buffer[num_info*5+2]);
在调试器中,recX似乎只加载了2个字节,但语法似乎不匹配。

Byte()
只是将一个字节大小值(此处为AnsiChar)转换为字节类型

最后一行代码由两个字节组成两字节变量
recX
(但不考虑可能的溢出效应)

Byte()
只是将一个字节大小值(此处为AnsiChar)转换为字节类型

最后一行代码由两个字节组成两字节变量
recX
(但不考虑可能的溢出效应)


PAnsiChar
始终具有一个很好的属性,您可以访问指向的
AnsiChar
,以及以下
AnsiChar
s,使用索引表示法,如数组(字节或
AnsiChar
s)。这就是为什么在这里使用它

现在,在具有
{$POINTERMATH}
的现代版本中,您更愿意使用
PByte
,它启用了相同的索引

recInstance
分配偏移量处的字节
numinfo*5
recX
分配以下两个字节作为单个16位值

在当前版本中,可以这样编写:

buffer: PByte;
n: Integer;

...

n := num_info * 5;
recInstance := buffer[n];
recX := buffer[n+1] or (buffer[n+2] shl 8); // together a 16 bit value

正如Remy所暗示的,您可以使用以下命令一次读取所有三个字节:

type
  PRec = ^TRec;
  TRec = packed record
    Instance: Byte; 
    X: Smallint; // a 16 bit (i.e. 2 byte) signed integer.
  end; // total size: 3 bytes.

var
  MyRec: TRec;

...

  MyRec := PRec(@buffer[num_info * 5])^;
PRec
cast将
@buffer[num_info*5]
返回的地址重新解释为指向
TRec
的指针,然后(使用
^
)取消引用,并将结果分配给
MyRec

换句话说,
@buffer[…]
是一个指针,
PRec(…)
将其转换为
PRec
类型的指针,
PRec(…)^
获取该指针处的3个字节,就好像它是
TRec
一样


MyRec.X
现在与
recX
相同,
MyRec.Instance
现在与原始代码中的
recInstance
相同。
PAnsiChar
始终具有可以访问所指向的
AnsiChar
的良好属性,以及以下使用索引表示法的
AnsiChar
s,如数组(字节或
AnsiChar
s)。这就是为什么在这里使用它

现在,在具有
{$POINTERMATH}
的现代版本中,您更愿意使用
PByte
,它启用了相同的索引

recInstance
分配偏移量处的字节
numinfo*5
recX
分配以下两个字节作为单个16位值

在当前版本中,可以这样编写:

buffer: PByte;
n: Integer;

...

n := num_info * 5;
recInstance := buffer[n];
recX := buffer[n+1] or (buffer[n+2] shl 8); // together a 16 bit value

正如Remy所暗示的,您可以使用以下命令一次读取所有三个字节:

type
  PRec = ^TRec;
  TRec = packed record
    Instance: Byte; 
    X: Smallint; // a 16 bit (i.e. 2 byte) signed integer.
  end; // total size: 3 bytes.

var
  MyRec: TRec;

...

  MyRec := PRec(@buffer[num_info * 5])^;
PRec
cast将
@buffer[num_info*5]
返回的地址重新解释为指向
TRec
的指针,然后(使用
^
)取消引用,并将结果分配给
MyRec

换句话说,
@buffer[…]
是一个指针,
PRec(…)
将其转换为
PRec
类型的指针,
PRec(…)^
获取该指针处的3个字节,就好像它是
TRec
一样


MyRec.X
现在与
recX
相同,
MyRec.Instance
现在与原始代码中的
recInstance
相同。

我将使用
PSmallint
类型转换,而不是手动连接字节:
recX:=PSmallint(@buffer[n+1])^
或更好,定义一个压缩记录,并将其转换为:
type PRec=^TRec;TRec=压缩记录持续时间:字节;recX:Smallint;结束。。。var缓冲区:PAnsiChar{或PByte};rec:TRec。。。rec:=PRec(@buffer[num_info*5])^@Remy:我想起来了。但我认为这并不能真正澄清问题,因为对于理解这里的PAnsiChar的用法有困难的人来说,
PRec(@buffer[n])^
语法更难理解。我想让事情尽可能简单。偏移量是'num_info乘以5'吗?因为数据类型是指针,所以星号是让每个人都不满意的地方。@Remy:我用你的建议更新了答案。谢谢。@AIG:我怀疑这会让很多了解帕斯卡/德尔福的人失望<代码>*
仅用于乘法。指针是与
^
一起声明和使用的,而不是与
*
一起声明和使用的。这不是C或类似C的语言。你的评论有点像一个Pascal程序员问为什么那些C语言的人把他们所有的代码都放在评论里我将使用
PSmallint
类型转换,而不是手动连接字节:
recX:=PSmallint(@buffer[n+1])^
或更好,定义一个压缩记录,并将其转换为:
type PRec=^TRec;TRec=压缩记录持续时间:字节;recX:Smallint;结束。。。var缓冲区:PAnsiChar{或PByte};rec:TRec。。。rec:=PRec(@buffer[num_info*5])^@Remy:我想起来了。但我认为这并不能真正澄清问题,因为对于理解这里的PAnsiChar的用法有困难的人来说,
PRec(@buffer[n])^
语法更难理解。我想让事情尽可能简单。偏移量是'num_info乘以5'吗?因为数据类型是指针,所以星号是让每个人都不满意的地方。@Remy:我用你的建议更新了答案。谢谢。@AIG:我怀疑这会让很多了解帕斯卡/德尔福的人失望<代码>*
仅用于乘法。指针是与
^
一起声明和使用的,而不是与
*
一起声明和使用的。这不是C或类似C的语言。你的评论有点像一个Pascal程序员问为什么那些C语言的人把他们所有的代码都放在评论里