Форум: "Основная";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];
ВнизДинамические массивы - правильно ли я понял 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;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.038 c