Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
14-1117824070
Мучимый жаждой
2005-06-03 22:41
2005.06.29
На чем писали самый первый язык программирования?


4-1114721597
i-s-v
2005-04-29 00:53
2005.06.29
Постраничная организация памяти?


1-1117614507
SergeiX
2005-06-01 12:28
2005.06.29
использование TListBox и TEdit


3-1116328809
ANB
2005-05-17 15:20
2005.06.29
Агрегирующая функция для строк и дат. (Oracle)


9-1111645986
ninja
2005-03-24 09:33
2005.06.29
интерфейс пользователя в игре





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский