为什么在使用readbuffer时使用string [1]而不是string

时间:2010-07-07 07:37:48

标签: delphi delphi-2007 delphi-2006

我有这样的记录

  TEmf_SrectchDIBits = packed record
    rEMF_STRETCHDI_BITS: TEMRStretchDIBits;
    rBitmapInfo: TBitmapInfo;
    ImageSource: string;
  end;
  ---
  ---
  RecordData: TEmf_SrectchDIBits;

如果我正在使用TStream将数据读入其中,则会发生异常

SetLength(RecordData.ImageSource, pRecordSize);

EMFStream.ReadBuffer(RecordData.ImageSource,pRecordSize) 

但是,如果我使用下面的代码,它正常工作

SetLength(RecordData.ImageSource, pRecordSize);

EMFStream.ReadBuffer(RecordData.ImageSource[1], pRecordSize);

那么使用String和String [1]

之间的区别是什么?

2 个答案:

答案 0 :(得分:12)

区别在于与.ReadBuffer方法的签名相关的详细信息。

签名是:

procedure ReadBuffer(var Buffer; Count: Longint);

如您所见,Buffer参数没有类型。在这种情况下,您说您想要访问基础变量。

但是,字符串是两部分,一个指针(变量的内容)和字符串(变量指向它)。

所以,如果ReadBuffer只给出了字符串变量,它将有4个字节来存储数据,字符串变量,并且这不会很好,因为字符串变量应该保存一个指针,而不仅仅是随机二进制数据。如果ReadBuffer写入超过4个字节,它将用新数据覆盖内存中的其他内容,这可能是一个灾难性的操作。

通过将[1]字符传递给var参数,您可以让ReadBuffer访问字符串变量指向的数据,这就是您想要的。您想要更改字符串 content

另外,请确保您已将字符串变量的长度设置为足以容纳您正在读取的内容。

另外,最后一点,我无法验证。在较旧的Delphi版本中,字符串变量包含1个字节的字符。在较新的情况下,由于unicode,我认为它们是两个,因此代码可能无法在较新版本的Delphi中按预期工作。您可能希望使用字节数组或堆内存。

答案 1 :(得分:5)

字符串类型实际上是作为指向我们可以称为“字符串描述符块”的指针实现的。基本上,你有一个间接的水平。 该块包含负偏移处的一些字符串控制数据(引用计数,长度以及更高版本的字符集信息),以及正数字符串字符串。字符串变量是描述块的指针(如果你打印SizeOf(stringvar)你得到4),当你处理字符串时,编译器知道在哪里找到字符串数据并处理它们。但是当使用无类型参数(var Buffer;)时,编译器不知道,它只是访问“Buffer”中的内存,但是使用字符串变量指针到字符串块,不是实际的字符串字符。使用字符串[1]传递第一个字符数据的位置。