Зачем использовать строку [1], а не строку при использовании readbuffer - PullRequest
4 голосов
/ 07 июля 2010

У меня такая запись

  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 ]

12 голосов
/ 07 июля 2010

Разница - это деталь, связанная с сигнатурой метода .ReadBuffer.

Подпись:

procedure ReadBuffer(var Buffer; Count: Longint);

Как видите, параметр Buffer не имеет типа. В этом случае вы говорите, что хотите получить доступ к базовой переменной.

Однако строка состоит из двух частей: указателя (содержимое переменной) и строки (переменная указывает на это).

Таким образом, если бы для ReadBuffer была задана только строковая переменная, у него было бы 4 байта для хранения данных, строковая переменная, и это не сработало бы слишком хорошо, поскольку строковая переменная должна содержать указатель, а не просто какой-либо случайные двоичные данные. Если бы ReadBuffer записал более 4 байтов, он перезаписал бы что-то еще в памяти новыми данными, что могло бы привести к катастрофическим последствиям.

Передавая символ [1] параметру var, вы предоставляете ReadBuffer доступ к данным, на которые указывает строковая переменная, что вам и нужно. Вы хотите изменить строку content в конце концов.

Кроме того, убедитесь, что вы установили длину строковой переменной достаточно большой, чтобы вместить в нее все, что вы читаете.

Кроме того, последнее замечание, которое я не могу проверить. В более старых версиях Delphi строковая переменная содержала 1-байтовые символы. В более новом, я думаю, что они два из-за Unicode, так что код может работать не так, как ожидалось в новых версиях Delphi. Вы, вероятно, хотели бы использовать вместо этого байтовый массив или кучную память.

5 голосов
/ 07 июля 2010

Строковые типы реализованы фактически как указатели на то, что мы могли бы назвать «блоком дескриптора строки». По сути, у вас есть уровень косвенности. Этот блок содержит некоторые строковые данные управления (счетчик ссылок, длину, а также информацию о наборе символов в более поздних версиях) с отрицательными смещениями и строковые символы с положительными. Строковая переменная - это указатель на блок расшифровки (и если вы печатаете SizeOf (stringvar), вы получаете 4), когда вы работаете со строками, компилятор знает , где найти строковые данные и справиться с ними. Но при использовании нетипизированного параметра (var Buffer;) компилятор не знает об этом, он просто получит доступ к памяти в «Buffer», но со строковой переменной, которая является указателем на строковый блок, а не фактические строковые символы. Используя строку [1], вы передаете местоположение данных первого символа.

...