Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.06.29;
Скачать: CL | DM;

Вниз

Динамические массивы - правильно ли я понял help?   Найти похожие ветки 

 
Ega23 ©   (2005-06-01 14:41) [0]

Никогда не работал с дин.массивами. Хочется узнать - правильно ли я понял, как с ними работать?

Допустим:
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;

Так ли это?


 
begin...end ©   (2005-06-01 14:43) [1]

> Ega23 ©   (01.06.05 14:41)

> Сохранились ли предыдущие значения a[0] и a[4]?

Да.

> Опреация по освобождению массива

Если это уже конец подпрограммы, то это делать необязательно. Дин. массив освободится автоматически пр выходе из области видимости.


 
TUser ©   (2005-06-01 14:43) [2]

Все правильно. Элементы 0-4 сохранятся. + хорохо бы еще finally поставить.

Hint: Если массив объявлен как локальная переменная, то Delphi гарантирует освобождение памяти по завершении работы процедуры.


 
Юрий Зотов ©   (2005-06-01 14:45) [3]

> в массиве 5 элементов.
Да.

> Индексация в массиве - с 0 до Length(a)-1
Да. Еще можно использовать Low(a) и High(a).

> Сохранились ли предыдущие значения a[0] и a[4]?
Да. Сохранились вообще все элементы, включая и мусорные.

> Опреация по освобождению массива
Либо так, либо a := nil.


 
Ega23 ©   (2005-06-01 14:46) [4]

Спасибо всем.


 
Ega23 ©   (2005-06-01 14:52) [5]

Вдогонку ещё один вопрос:
Могу ли я после задания длины массиву (SetLength(a, Count)) использовать переменную a в виде буфера при чтении из Stream?

var
a:array of integer;
Count:Integer;
ms:TMemoryStream;
begin

ms:=TMemoryStream.Create;
try
 TBLOBField(Query1.FieldByName("Data")).SaveToStream(ms);
 Count:=Query1.FieldByName("DataLength").AsInteger;
 ms.Position:=0;
 SetLength(a, Count);
 ms.ReadBuffer(a, Count*SizeOf(Integer));
 
  ......

finally
 ms.Free;
 a:=nil;
end;

end;


 
Amoeba ©   (2005-06-01 14:54) [6]

ms.ReadBuffer(a[0], Count*SizeOf(Integer));


 
Ega23 ©   (2005-06-01 14:57) [7]

А почему a[0]?


 
begin...end ©   (2005-06-01 14:59) [8]

> Ega23 ©   (01.06.05 14:57) [7]

Потому что иначе (как в коде [5]) ты будешь читать не в область, в которой расположены элементы массива, а в указатель на эту область.


 
КаПиБаРа ©   (2005-06-01 14:59) [9]

Ega23 ©   (01.06.05 14:57) [7]
Так нада.
a[0] - адрес первого элемента массмива
a - адрес где храится сцылка на a[0]


 
begin...end ©   (2005-06-01 15:01) [10]

> КаПиБаРа ©   (01.06.05 14:59) [9]

> a[0] - адрес первого элемента массмива

a[0] -- это не адрес. Это сам элемент.


 
Ega23 ©   (2005-06-01 15:02) [11]

Ага, спасибо. В общем, всё также, как и в "ручном" формировании динамического массива, только без GetMem - FreeMem


 
evvcom ©   (2005-06-01 15:02) [12]


> А почему a[0]?

Потому что procedure ReadBuffer(var Buffer; Count: Longint);
Передаешь a[0] по ссылке, компилятор подставляет адрес 0-го элемента, если передавать a, то передашь адрес переменной a-указателя на динамический массив.


 
evvcom ©   (2005-06-01 15:05) [13]


> только без GetMem - FreeMem

зато с (+) Length, Low и High, хотя для дин.массивов Low всегда = 0


 
Ega23 ©   (2005-06-01 15:36) [14]

Откровенно говоря, когда в университете проходили списки и способы их построения, всяческими array of и TList при написании заданий пользоваться было категорически запрещено.
Ну, TList я с тех пор худо-бедно освоил :)
А вот с массивами как-то не срослось. Да и надобности не было...


 
Юрий Зотов ©   (2005-06-01 16:54) [15]

> Ega23 ©   (01.06.05 14:52) [5]

Чтобы использовать что-то типа
ReadBuffer(a[0], Length(a) * SizeOf(тип_элемента))
массив, строго говоря, должен быть объявлен так:
a: packed array of тип_элемента

Тут этот вопрос когда-то обсуждался и выяснилось, что компилятор пакует массивы даже и при отсутствии packed, но я бы все же рекомендовал указывать packed явно. Как минимум, по трем причинам:
- гарантирует от возможных коллизий в будущих версиях;
- дисциплинирует мозги;
- код становится прозрачнее.


 
Ega23 ©   (2005-06-01 17:21) [16]


> a: packed array of тип_элемента

Спасибо. Это ценная информация.
Для статических массивов при описании структуры я packed использую, но про динамические - не знал.


 
Суслик ©   (2005-06-01 17:25) [17]


>  [15] Юрий Зотов ©   (01.06.05 16:54)

Знаешь, Юрий, на слово packed кладут, как мне показалось все, в том числе и сами разработчики borland. Такое ощущение, что они не собираются реализовывать соответствующую семантику вообще.

Я, кстати, всегда пишу, когда это нужно. Но есть ощущение, что это лишнее.


 
Defunct ©   (2005-06-02 03:18) [18]

Юрий Зотов ©   (01.06.05 16:54) [15]
> строго говоря, должен быть объявлен так:
> a: packed array of тип_элемента

скорее, не строго говоря, а в тех случаях когда тип_элемента - record и не объявлен с ключевым словом packed либо не кратен 4.

a: packed array of integer  
не красиво ;>
А вдруг (что маловероятно) первый элемент при этом окажется невыровняным на границу Dword? тогда работа с таким массивом на некоторых процессорах будет неоправдано медленной.


 
begin...end ©   (2005-06-02 09:12) [19]

> Defunct ©   (02.06.05 03:18) [18]

> скорее, не строго говоря, а в тех случаях когда тип_элемента
> - record и не объявлен с ключевым словом packed либо не
> кратен 4.

И на что в этом случае повлияет слово packed перед array?


 
evvcom ©   (2005-06-02 09:27) [20]


> А вдруг (что маловероятно) первый элемент при этом окажется
> невыровняным на границу Dword

Первый уж точно будет выровнен, вот остальные ...


 
Defunct ©   (2005-06-02 09:44) [21]

> begin...end

не знаю. А что вы об это думаете?


> evvcom
там же ж слово packed, остальные будут будут "притиснуты" друг к другу.


 
begin...end ©   (2005-06-02 09:45) [22]

> Defunct ©   (02.06.05 09:44) [21]

> А что вы об это думаете?

Я думаю, что никак.


 
begin...end ©   (2005-06-02 09:46) [23]

В смысле, ни на что не повлияет.


 
Defunct ©   (2005-06-02 09:54) [24]

мне все-таки кажется, что хотя бы record к record"у прижмет вплотную.


 
begin...end ©   (2005-06-02 09:55) [25]

> Defunct ©   (02.06.05 09:54) [24]

А разве без packed перед array записи не будут прижаты друг к другу?


 
evvcom ©   (2005-06-02 09:56) [26]


> там же ж слово packed, остальные будут будут "притиснуты"
> друг к другу

Я это знаю. Я говорил о варианте без packed.


 
jack128 ©   (2005-06-02 09:57) [27]

Defunct ©   (02.06.05 9:44) [21]
там же ж слово packed, остальные будут будут "притиснуты" друг к другу

не на всех платформах SizeOf(Integer) = Size(DWord). Хотя на это можно забить.

Defunct ©   (02.06.05 3:18) [18]
скорее, не строго говоря, а в тех случаях когда тип_элемента - record и не объявлен с ключевым словом packed либо не кратен 4

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

Суслик ©   (01.06.05 17:25) [17]
на слово packed кладут, как мне показалось все, в том числе и сами разработчики borland. Такое ощущение, что они не собираются реализовывать соответствующую семантику вообще.


 
Defunct ©   (2005-06-02 10:01) [28]

begin...end ©   (02.06.05 09:55) [25]

Возможены случаи когда не будут.
SizeOf(<Record>) = 31, будут или не будут?


 
Defunct ©   (2005-06-02 10:03) [29]

> jack128
> Хотя разговор довольно бессмысленный так как

ну для чего-то же все-таки есть ключевое слово packed. не может быть чтобы оно было просто бессмысленным.


 
Игорь Шевченко ©   (2005-06-02 10:10) [30]

jack128 ©   (02.06.05 09:57) [27]


> На самом деле если еще более абстрагироваться от конкретных
> платформ, то неупаковонный массив должен обеспечивать наиболее
> быстрый доступ к массиву


Безусловно.

Defunct ©   (02.06.05 10:03) [29]


> ну для чего-то же все-таки есть ключевое слово packed. не
> может быть чтобы оно было просто бессмысленным


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


 
Defunct ©   (2005-06-02 10:29) [31]

> Игорь Шевченко
> Во-первых, оно обеспечивает совместимость на уровне двоичного кода функций, написанных на разных языках

Напрашивается вопрос.

TRecord = record
F1..FN : Sometype
...
End;


TArray = packed array of TRecord

Будет ли TArray соответствовать вышесказанному?


 
Ega23 ©   (2005-06-02 10:34) [32]

2 Defunct ©   (02.06.05 10:29) [31]

Насколько я понял, имеется ввиду совместимость структуры на C и рекорда в Delphi. Ну, грубо говоря, как соглашение о вызове у функции.
Я packed использовал только для чтения хитрых бинарников и формировании данных для передачи по сети.


 
Юрий Зотов ©   (2005-06-02 10:39) [33]

> Defunct ©   (02.06.05 03:18) [18]

> скорее, не строго говоря, а в тех случаях когда
> тип_элемента - record и не объявлен с ключевым
> с ключевым словом packed либо не кратен 4.

Имеем динамический массив A с типом элемента byte. Есть поток MS класса TMemoryStream размером 12 байт, которые содержат:
$01 $02 $03 $04 $05 $06 $07 $08 $09 $0A $0B $0C

Программа содержит операторы:

SetLength(A, MS.Size);
MS.Position := 0;
MS.ReadBuffer(A[0], Length(A) * SizeOf(byte));

Теперь вопрос (напоминаю, что директива packed имеет значение, если говорить именно строго - то есть, когда отсутствие этой директивы компилятором НЕ игнорируется, как оно и должно быть). Итак:

Как будет заполнен массив A в каждом из двух случаев:
- когда он упакован;
- когда он НЕ упакован.

Ответы:

- упакованный массив будет содержать в себе точную копию тела потока (поэлементно - см. выше).

- говоря строго, неупакованный массив будет содержать в себе следующее (буква M означает элемент массива, содержащий "мусор"):
$01 $05 $09 М M M M M M M M M
(предполагается умалчиваемое выравнивание для 32-битных платформ - на границу двойного слова).

- говоря НЕ строго, неупакованный массив будет содержать в себе то же самое, что и упакованный.

Что же мы видим уже на этом элементарном примере?
1. Заполнение массива зависит от его упакованности именно говоря строго.
2. Никакие record"ы тут ни при чем - различие наблюдается даже на скалярных типах.


 
Defunct ©   (2005-06-02 10:41) [34]

packed = упакованый.
не обращаясь к справке, только по смыслу этого слова можно допустить, что независимо от компилятора каждое поле упакованой структуры будет размещено байт к байту с другими полями.
Вот собсно в этом вопрос, так ли это.

Достатоточно ли объявить packed array of TRecord, чтобы неупакованые записи стали упаковаными в массиве?


 
Defunct ©   (2005-06-02 10:44) [35]

> Юрий Зотов
запостил [34] до того как появился Ваш ответ [33]. Но тем не менее если не трудно, можете ответить на [34]?


 
evvcom ©   (2005-06-02 10:49) [36]


> Достатоточно ли объявить packed array of TRecord, чтобы
> неупакованые записи стали упаковаными в массиве?

Допустим SizeOf(TRecord)=6. Принимая во внимание сказанное (написанное) Юрием, packed array[0..1] будет состоять из 12 байт, а не упакованный из 16. Сами же TRecord как были не упакованными, так и останутся.


 
Юрий Зотов ©   (2005-06-02 10:52) [37]

> Defunct ©   (02.06.05 10:44) [35]

Точно не знаю, не проверял. Но можно проверить указанным в [33] способом.


 
evvcom ©   (2005-06-02 10:54) [38]

Кстати, в "потрепаться" затрагивался вопрос о нужности или не нужности понимания ассемблера. Вот он пример. Понимая асм программист может многое понять, не тратя гораздо большее время на поиски в интернете.


 
Defunct ©   (2005-06-02 10:56) [39]

evvcom ©   (02.06.05 10:49) [36]

Вполне логично, вечером проверю. Сейчас под рукой нет ни Delphi ни даже справки от него.


 
evvcom ©   (2005-06-02 11:09) [40]

Я уже проверил.

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



Страницы: 1 2 вся ветка

Текущий архив: 2005.06.29;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.028 c
3-1116233305
Yurisimus
2005-05-16 12:48
2005.06.29
DataSource не видит pFIBQuery


1-1118222933
Ярослав
2005-06-08 13:28
2005.06.29
Сохранить файл в Unicode


4-1115117068
Steepesson
2005-05-03 14:44
2005.06.29
резидентная программа


14-1117814291
Новичоккк
2005-06-03 19:58
2005.06.29
Delphi 7 vs Delphi 8 vs Delphi 2005


14-1117602690
Vlad Oshin
2005-06-01 09:11
2005.06.29
Извините за вчерашнее.