Запись с самим массивом в Delphi

#delphi #data-structures #structure #record

#delphi #структуры данных #структура #запись

Вопрос:

Кто-нибудь знает, как сделать что-то подобное?

 type TFileRecord = record
    Name: String;
    CreationTimeStamp: DWORD;
    Subfiles: Array of TFileRecord;
end;
 

Я использую Delphi 10.4.

Комментарии:

1. Сэмюэль Андраде: Боюсь, трудно сказать, что именно вы спрашиваете. Если вы скопируете этот код в программу или модуль Delphi и нажмете кнопку компиляции, он будет скомпилирован и будет работать так, как ожидалось.

2. Я предполагаю, что сторонники поддержки понимают, о чем спрашивает OP. Не могли бы вы, пожалуйста, объяснить мне?

3. … динамический массив — это ссылочный тип (просто указатель на объект кучи динамического массива). Итак, хотя ваш приведенный выше код, который использует динамический массив, работает хорошо ( Subfiles это просто 32-разрядный или 64-разрядный указатель.), теоретически невозможно заменить его статическим массивом. Потому что, если вы подумаете об этом, вы поймете, что это сделало бы размер TFileRecord бесконечным!

4. @SamuelAndrade, я откатил вопрос, поскольку он полностью меняет вопрос. Вам лучше задать новый вопрос.

5. Я поддержал вопрос (после того, как увидел, что у него есть отрицательные голоса), поскольку, хотя вопрос был немного плохо сформулирован (он действительно должен был спросить: «Это допустимая конструкция?»), Было довольно очевидно, что «это допустимо?» это был реальный вопрос, и он был интересным.

Ответ №1:

В моем Delphi 10.4.1, безусловно, возможно иметь такое объявление:

 unit TestUnit;

interface

type
  TFileRecord = record
    Name: String;
    CreationTimeStamp: Cardinal; //DWORD;
    Subfiles: Array of TFileRecord;
  end;

Procedure TestTFR;

implementation

Procedure TestTFR;
var
  TFR : TFileRecord;
begin
  SetLength(TFR.SubFiles,2);
  SetLength(TFR.Subfiles[0].Subfiles,2);
end;    

end.
 

Эта функция была введена в Delphi 2009.
До этого компилятор жаловался на то, что TFileRecord еще не полностью определен.

Как обсуждалось в комментариях, размер динамического массива может быть только размером указателя, что архитекторы компилятора поняли в то время. Зная это, завершение объявления типа не имеет значения для однопроходного компилятора.

Комментарии:

1. Отлично компилируется и в Delphi XE7.

2. Интересно, что это работает только в том случае, если у вас есть объект (может быть либо запись, либо класс), который содержит динамический массив объектов одного и того же типа. Но когда вы пытаетесь объявить объекты, которые имеют тот же тип объекта, что и поле, или содержат статический массив одинаковых типизированных объектов, Delphi выдает ошибку, тип которой еще не полностью определен.

3. Я предполагаю, что компилятор достаточно умен, чтобы знать, что в случае динамического массива объекты, содержащиеся в массиве, будут храниться в их собственных блоках памяти, поэтому их размер не важен при создании объекта, который содержит такой динамический массив. Но если такие объекты будут определены как поля или в массиве фиксированного размера, они могут храниться в том же блоке памяти, что и объект, который их содержит. в таком случае вам нужно заранее знать размер и структуру этого объекта.

4. PS: Кто-нибудь знает хорошую статью или книгу, в которой более подробно объясняется, как Delphi memory Manager хранит разные объекты. Я думаю, это может быть интересным чтением. И да, я знаю, что FastMM является открытым исходным кодом, но я сомневаюсь, что мои знания Delphi достаточно хороши, чтобы понять его внутренности в отношении этого, просто просмотрев его исходный код.

5. @SilverWarior: если тип записи содержит поле своего собственного типа, вы получаете запись бесконечного размера, теоретическую концепцию, которую невозможно реализовать. А статические массивы — это типы значений, так array[0..3] of X что это то же самое, record dummy1, dummy2, dummy3, dummy4: X end что и для заполнения, за исключением. Следовательно, если тип записи содержит поле типа static array самой записи, вы снова получаете эту бесконечную рекурсию и невозможную конструкцию. Все, что вам нужно знать о внутренних форматах данных, находится по адресу docwiki.embarcadero.com/RADStudio/Rio/en /.