TArray<Byte>、TBytes和PByteArray的区别是什么?

5

这三种类型非常相似...

TArray是TBytes的通用版本。 两者都可以转换为PByteArray,并用作调用Windows API的缓冲区。(与字符串到Pchar的限制相同)。

我想知道的是:这种行为是“按设计”还是“按实现”?更具体地说,它在未来的版本中是否会出现问题?

//编辑 如下所述... 我真正想知道的是:将TBytes(或TArray)强制转换为PByteArray是否像将String强制转换为PChar那样安全,就前向兼容性而言。(或者AnsiString到PAnsiChar可能是一个更好的例子^_^)

2个回答

3

这三种类型中有两种是相似的(实际上是相同的),第三种则不同。

TArrayTBytes都被声明为“Byte 数组”,但你漏掉了另一种非常相关的类型:TByteArray(由PByteArray引用的类型)。

PByteArray 是指向TByteArray的指针,严格来说它是指向静态字节数组的指针,而不是动态数组(其他字节数组类型都是动态数组)。 它以这种方式进行类型化,以便使用整数索引引用从该基本指针偏移的位置。 请注意,此索引仅限于2^15个元素(0..32767)。 对于从某个基本指针开始的任意字节偏移量(> 32767),PByteArray 是无用的:

var
  b: Byte;
  ab: TArray<Byte>;
  pba: PByteArray;
begin
  SetLength(ab, 100000);
  pba := @ab;             // << No cast necessary - the compiler knows (magic!)
  b   := pba[62767];      // << COMPILE ERROR!
end;

即将一个字节数组TArray转换为PByteArray可能会导致问题,其中数组具有>32K个元素(并且指针被传递到尝试访问所有元素的某些代码)。当然,将其转换为未类型化的指针可以避免这种情况(只要指针的“接收者”适当地处理对指针引用的内存访问)。

但是,这些都不太可能在未来发生改变,它仅仅是实现细节的结果,这些细节长期以来一直适用于这个领域。引入语法上糖衣的泛型类型声明是一个kipper rouge


顺便提一下,如果需要,可以通过重新声明本地类型来绕过32767限制。 类型 PByteArray = ^TByteArray; TByteArray = array[0..MaxInt - 1] of Byte; - Ken Bourassa
“Kipper rouge”是什么意思? - Rob Kennedy
抱歉 - Kipper Rouge = “Red Herring” :) - Deltics

3
简单来说,字节数组就是一组字节,只要字节和数组的定义不改变,这个定义也不会改变。只要确保尊重数组边界限制,就可以安全地使用它,因为从Delphi的数组类型中强制转换出来会使边界检查失效。
编辑:现在我更好地理解你的问题了。
不,你不应该将动态数组引用强制转换为C样式数组指针。对于字符串,你可以这样做,因为编译器会帮助你一些。
但你可以将动态数组元素0的指针强制转换为C样式数组指针。那样可以工作,并且不会改变。

实际上,您错了... "Array of byte" 不是一个字节数组... 它是一个指向动态字节数组的指针,该数组是引用计数和长度管理的(几乎像字符串一样)。我想知道的是:就前向兼容性而言,将 TBytes(或 TArray<Byte>)强制转换为 PByteArray 是否与将 String 强制转换为 PChar 一样安全。 - Ken Bourassa
“Byte”数组是一个字节数组。唯一的区别在于,它主要作为引用类型而不是值类型(如静态数组)出现在运行时中。编译器当然知道这一点,并且会(好吧,应该会)像对待String <> PChar一样为您处理类型转换(通常称为“编译器魔法”——即依赖于编译器自身内部意识的代码生成)。 - Deltics
@Ken: 好的,我明白你的意思了。正在编辑我的回复。 - Mason Wheeler
编译器在将字符串转换为PChar时几乎不做任何事情。它将字符串指针放入PChar中,除非字符串为空,否则它将返回指向#0字符的指针。 String有12个字节的头(从D2010开始,之前是8个字节),并保留Length+1个字符的内存。(String[Length+1]是每个字符串自动保留的隐式空终止字符,因此它们可以被转换为PChar)。所以引用类型...指针...对我来说基本相同。除了它还有一些额外的装饰。(引用计数等) - Ken Bourassa
@Ken:它可能没有做太多事情,但它知道它可以允许它。 - Deltics

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接