![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Динамические массивы - правильно ли я понял help?
Ega23 © (2005-06-01 14:41:00)Никогда не работал с дин.массивами. Хочется узнать - правильно ли я понял, как с ними работать?
Допустим:
var
a:array of Integer;
begin
SetLength(a, 5); // в массиве 5 элементов.
a[0]:=1; a[4]:5; // Индексация в массиве - с 0 до Length(a)-1
SetLength(a, 6); // Сохранились ли предыдущие значения a[0] и a[4]?
SetLength(a, 0) // Опреация по освобождению массива
end;
Так ли это?
Sapersky (2005-06-02 15:15:00) [1]Логика выравнивания полей неупакованных записей довольно хитрая, это не просто "расставить поля по адресам кратным 4".
См. хелп: Object Pascal Reference \ Memory management \ Record types
Массивы, видимо, выравниваются по такому же принципу.
evvcom (2005-06-02 12:39:00) [2]Кстати, переделал код:
type
TRecord = record
dw: DWORD;
c: Char;
end;
const
ac1: TRecord = (dw: $11111111; c: 'A');
ac2: TRecord = (dw: $22222222; c: 'B');
var
a1: array[0..1] of TRecord;
a2: packed array[0..1] of TRecord;
begin
a1[0] := ac1;
a1[1] := ac2;
a2[0] := ac1;
a2[1] := ac2;
end;
Компилятор между этими массивами опять не видит никакой разницы, но результат теперь такой:
11 11 11 11 41 00 00 00
22 22 22 22 42 00 00 00
Проверил SizeOf(TRecord), теперь он =8, хотя в предыдущем был =6. Вот этим 8 и 6 я что-то объяснения найти не могу пока.
begin...end (2005-06-02 12:23:00) [3]> Defunct © (02.06.05 12:18) [53]
> Обязательно надо было ложку дёгтя в бочку мёда засунуть?
> Было бы "по-моему" еще неизвестно как сделал бы.
Я просто не понял, как Вы себе представляете действия компилятора в данном случае. Потому и спросил.
Defunct (2005-06-02 12:18:00) [4]> begin...end
Все было просто отлично, доходчиво и логично, до вот этого:
По-Вашему, компилятор будет брать каждое поле из присваиваемой записи и помещать его в соответствующее поле упакованного элемента массива, вместо того чтобы скопировать целиком неупакованную запись?
Обязательно надо было ложку дёгтя в бочку мёда засунуть?
Было бы "по-моему" еще неизвестно как сделал бы.
> не с этим ли связано появление reserved агрументов в некоторых API функциях
Вполне возможно.
TUser (2005-06-02 12:08:00) [5]> > А как же заставить компилятор чтобы массив был НЕ упакованым?
Можно обявить array of TCoolRecord, где в TCoolRecord забить нужное кол-во бополнительных полей соотвествующего размера, например
TCoolRecord =
record
B1, B2: boolean; // 2 байта
C1, С2, С3: shortint; // 3 байта
Zero: array [0..2] of byte; // not used
end;
Интересно, не с этим ли связано появление reserved агрументов в некоторых API функциях?)
begin...end (2005-06-02 12:08:00) [6]> Defunct © (02.06.05 10:01) [28]
> Возможены случаи когда не будут.
Если утверждаете, то, вероятно, можете привести пример. Хотелось бы увидеть.
> SizeOf(<Record>) = 31, будут или не будут?
Будут.
> Defunct © (02.06.05 10:29) [31]
> TArray = packed array of TRecord
> Будет ли TArray соответствовать вышесказанному?
TArray будет упакованным, а его элементы будут неупакованными.
> Defunct © (02.06.05 10:41) [34]
> packed = упакованый.
> не обращаясь к справке, только по смыслу этого слова можно
> допустить, что независимо от компилятора каждое поле упакованой
> структуры будет размещено байт к байту с другими полями.
> Вот собсно в этом вопрос, так ли это.
Если запись объявлена с packed, то поля записи будут прижаты.
Если массив объявлен с packed, то элементы массива будут прижаты.
Если массив объявлен без packed, то элементы всё равно будут прижаты.
> Достатоточно ли объявить packed array of TRecord, чтобы
> неупакованые записи стали упаковаными в массиве?
Конечно, нет. Потому что в данном случае packed относится к размещению элементов массива, а не к размещению полей в этих элементах.
А если бы при таком объявлении записи упаковывались, как тогда выглядело бы присваивание значения элементу такого массива? По-Вашему, компилятор будет брать каждое поле из присваиваемой записи и помещать его в соответствующее поле упакованного элемента массива, вместо того чтобы скопировать целиком неупакованную запись?
По-моему, всё логично и понятно. Кроме того, что массивы всегда (независимо от наличия packed) упаковываются.
Alx2 (2005-06-02 12:03:00) [7]Defunct © (02.06.05 11:39) [49]
Увы. Компилятор Delphi (по крайней мере D6) не умеет делать требуемое выравнивание.
Чтобы это обойти, в критичных по скорости участках, я использую DLL, скомпилированные Intel C++ compiler. У него, кстати, кроме уже стандартных MMX, SSE, SSE2, SSE3 (в частности, для них он автоматом производит векторизацию и распараллеливание) есть оптимизация и под 64-битную архитектуру Itanium - пока еще большая редкость.
Defunct (2005-06-02 11:39:00) [8]evvcom © (02.06.05 11:32) [47]
На данный момент именно так и поступаю.
Alx2 © (02.06.05 11:33) [48]
Но они работают медленнее почти в 2 раза
речь о
movdqa
и
movdqu
Alx2 (2005-06-02 11:33:00) [9]Defunct © (02.06.05 11:30) [46]
Кажется, есть аналоги для невыровненных данных.
evvcom (2005-06-02 11:32:00) [10]
> А как же заставить компилятор чтобы массив был НЕ упакованым?
...
> Честно говоря - надо.
type
TRecord = record
c: Char;
w: WORD;
w1: WORD;
reserved: WORD;
end;
Defunct (2005-06-02 11:30:00) [11]> Суслик
Честно говоря - надо. Иначе бы и не спрашивал. Некоторые SSE команды работают только с данными, выровненными на границу QWORD иначе exception.
Anatoly Podgoretsky (2005-06-02 11:24:00) [12]Defunct © (02.06.05 10:41) [34]
Достатоточно ли объявить packed array of TRecord, чтобы неупакованые записи стали упаковаными в массиве?
В данном контексте packed относится к самому массиву, а не элементам записи.
Суслик (2005-06-02 11:20:00) [13]
> [42] Defunct © (02.06.05 11:15)
С трудом могу представить, когда это нужно. Как я говорил на это кладут сами разработчики borland. Не скажу где (т.к. не помню), но я вдиел в глубинах vcl игнорирование packed, хотя по месту это было необходимо.
Я сейчас постю и читаю группы на borland.com. Будет время спрошу про это.
Суслик (2005-06-02 11:17:00) [14]
> А как же заставить компилятор чтобы массив был НЕ упакованым?
>
А оно вам надо?
Defunct (2005-06-02 11:15:00) [15]> evvcom
ок, теперь все понятно. Вы были правы в [36].
> компилятор не делает разницы между packed array и не packed
А как же заставить компилятор чтобы массив был НЕ упакованым?
т.е. то про что говорил ЮЗ:
когда отсутствие этой директивы компилятором НЕ игнорируется
evvcom (2005-06-02 11:10:00) [16]+ А вот элементы массива по 6 байт, т.е. SizeOf(TRecord)
evvcom (2005-06-02 11:09:00) [17]Я уже проверил.
type
TRecord = record
c: Char;
w: WORD;
w1: WORD;
end;
const
ac1: TRecord = (c: 'A'; w: $10; w1: $55);
ac2: TRecord = (c: 'B'; w: $20; w1: $AA);
var
a1: array[0..1] of TRecord;
a2: packed array[0..1] of TRecord;
begin
a1[0] := ac1;
a1[1] := ac2;
a2[0] := ac1;
a2[1] := ac2;
end;
компилятор не делает разницы между packed array и не packed. Оба массива занимают по 12 байт:
41 00 10 00 55 00 42 00 20 00 AA 00
все hex
Defunct (2005-06-02 10:56:00) [18]evvcom © (02.06.05 10:49) [36]
Вполне логично, вечером проверю. Сейчас под рукой нет ни Delphi ни даже справки от него.
evvcom (2005-06-02 10:54:00) [19]Кстати, в "потрепаться" затрагивался вопрос о нужности или не нужности понимания ассемблера. Вот он пример. Понимая асм программист может многое понять, не тратя гораздо большее время на поиски в интернете.
Юрий Зотов (2005-06-02 10:52:00) [20]> Defunct © (02.06.05 10:44) [35]
Точно не знаю, не проверял. Но можно проверить указанным в [33] способом.