我们都将Delphi用于一个项目并且已经有多年了。 但我们从未见过与PAnsiChar一起使用的以下语法,并且不知道它的含义:
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个字节,但语法似乎不匹配。
答案 0 :(得分:2)
PAnsiChar
总是有一个很好的属性,你可以访问被指向的AnsiChar
,以及下面的AnsiChar
使用索引表示法,如数组(字节或{ {1}} S)。这就是为什么在这里使用它。
现在,在具有AnsiChar
的现代版本中,您宁愿使用{$POINTERMATH}
,而是启用相同的索引。
PByte
被赋予偏移量recInstance
的字节,numinfo*5
被分配以下两个字节作为一个单独的16位值。
在当前版本中,它可以写成:
recX
正如雷米暗示的那样,您可以使用以下方式一次读取所有三个字节:
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
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
返回的地址重新解释为指向@buffer[num_info * 5]
的指针,然后取消引用(使用TRec
),并将结果分配给^
。
换句话说,MyRec
是一个指针,@buffer[...]
将其转换为PRec(...)
类型的指针,PRec
获取该指针的3个字节,就好像它一样是PRec(...)^
。
TRec
现在与MyRec.X
相同,recX
现在与原始代码中的MyRec.Instance
相同。
答案 1 :(得分:0)
Byte()
只是将一个字节大小的值(此处为AnsiChar)类型转换为字节类型
最后一行代码行从两个字节形成双字节变量recX
(不考虑可能的溢出效应)
int16var = byte1 + 256 * byte2
//almost equivalent of
(byte2 shl 8) or byte1