TArray <Byte>VS TBytes VS PByteArray - PullRequest
5 голосов
/ 11 марта 2010

Эти 3 типа очень похожи ...

TArray - универсальная версия TBytes. Оба могут быть преобразованы в PByteArray и использованы в качестве буфера для вызовов Windows API. (с теми же ограничениями, что и для строки в Pchar).

Что я хотел бы знать: это поведение «по замыслу» или «по реализации». Или, точнее, он может сломаться в будущем выпуске?

// Редактировать Как указано ниже ... То, что я действительно хочу знать, это: безопасна ли передача типов TBytes (или TArray) в PByteArray так же, как это позволяет вводить String to PChar в части прямой совместимости. (Или, может быть, AnsiString для PAnsiChar - лучший пример ^ _ ^)

Ответы [ 2 ]

3 голосов
/ 11 марта 2010

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

РЕДАКТИРОВАТЬ: Я думаю, что теперь я вижу, что вы спрашиваете немного лучше.

Нет, вы не должны приводить ссылку на динамический массив к указателю массива в стиле C. Вы можете избежать неприятностей со строками, потому что компилятор немного вам поможет.

Однако вы можете привести указатель на элемент 0 динамического массива к указателю массива в стиле C. Это будет работать и не изменится.

1 голос
/ 11 марта 2010

Два из этих типов похожи (фактически идентичны). Третий нет.

TArray объявляется как " Массив байтов ", как и TBytes . Однако вы пропустили еще один очень актуальный тип, TByteArray (тип, на который ссылается PByteArray ).

Будучи указателем на TByteArray , PByteArray , строго говоря, является указателем на статический байтовый массив, а не на динамический массив (который все остальные типы байтовых массивов). Он набирается таким образом, чтобы разрешить ссылку на смещения от этого базового указателя с использованием целочисленного индекса. И обратите внимание, что это индексирование ограничено 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 .

...