代码之家  ›  专栏  ›  技术社区  ›  Bharat

为什么在使用readbuffer时使用字符串[1]而不是字符串?

  •  4
  • Bharat  · 技术社区  · 14 年前

    我有这样的唱片

      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);
    

    那么什么是 使用字符串和字符串的区别[1]

    2 回复  |  直到 14 年前
        1
  •  12
  •   Lasse V. Karlsen    14 年前

    差异是与.readBuffer方法的签名相关的详细信息。

    签名是:

    procedure ReadBuffer(var Buffer; Count: Longint);
    

    如您所见,缓冲区参数没有类型。在本例中,您的意思是希望访问基础变量。

    但是,字符串由两部分组成:指针(变量的内容)和字符串(变量指向此内容)。

    因此,如果只给readbuffer字符串变量,它将有4个字节来存储数据到字符串变量中,这就不太好了,因为字符串变量应该包含一个指针,而不仅仅是任何随机的二进制数据。如果readbuffer写入的字节数超过4个,它将用新数据覆盖内存中的其他内容,这可能是一个灾难性的操作。

    通过将[1]字符传递给 var 参数,您将为readbuffer提供对字符串变量指向的数据的访问,这正是您想要的。您要更改字符串 内容 毕竟。

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

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

        2
  •  5
  •   user160694    14 年前

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