Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.04.22;
Скачать: [xml.tar.bz2];

Вниз

Очистить массив из Integer-ов   Найти похожие ветки 

 
Dmitry_177   (2007-03-30 09:22) [0]

есть массив из Integer-ов.. Мне его надо очистить, делаю FillChar, чтобы заполнить его нулями.. И почему-то после этого если како-му то его элементу что-то присвоить, то будет ошибка AV. Вот так выскакивает AV:

var
 Codes: array of Integer;

procedure TForm1.Button1Click(Sender: TObject);
begin
 SetLength(Codes, 1);
 FillChar(Codes, SizeOf(Codes), 0);
 Codes[0] := 212;
 MessageBox(0, PChar(IntToStr(Codes[0])), "", 0);
end;

На строке Codes[0] := 212;

Подскажите пожалуста почему так?


 
ЮЮ ©   (2007-03-30 09:29) [1]

FillChar(Codes, SizeOf(Codes), 0);
зачем тут обнулять, если выделяешь 1 элемент и тут же его записываешь

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

Имхо, достаточно
Codes := nil;
перед новым наращиванием массива
SetLength(Codes, 1);


 
TRUNK ©   (2007-03-30 09:32) [2]


> Dmitry_177   (30.03.07 09:22)
> Подскажите пожалуста почему так?

Потому что массив динамический, и Codes на самом деле содержит указатель на массив. Поэтому FillChar обнуляет указатель, что равноценно Codes := nil, поэтому и последующее обращение к массиву вызывает AV.


 
begin...end ©   (2007-03-30 09:37) [3]

Потому что переменная, имеющая тип "динамический массив", по сути является указателем на тело массива, т.е. содержит адрес его первого (нулевого) элемента. Следовательно, в строке с FillChar Вы записываете нули не в тело массива, а в указатель на него. В результате ссылка портится -- теперь вместо реального адреса тела массива она содержит ноль. Поэтому дальнейшая попытка записи в массив с использованием этой ссылки приводит к AV -- ведь фактически Вы пытаетесь записать что-то по нулевому адресу, а чтение и запись из памяти / в память по такому адресу запрещены.

Чтобы правильно очистить такой массив, нужно строку с FillChar переписать так: FillChar(Codes[0], sizeof(Codes[0]) * Length(Codes), 0).

Однако, если речь идёт об очистке массива array of integer, только что инициализированного первым вызовом SetLength (как в приведённом примере), то это лишнее -- все элементы такого нового массива вначале содержат ноль.


 
Dmitry_177   (2007-03-30 09:40) [4]


> зачем тут обнулять, если выделяешь 1 элемент и тут же его
> записываешь

Это я к примеру же привел.. А мне надо к примеру выделить 100 элементов, и какие-то из них заполнить, а остальные что были нулями.. Вот я и подумал о том, что если выделить 100 элементов SetLength-ем, как бы там мусора небыло, чтобы не оказалось что какой-то элемент уже чему-то равен, вот и решил обнулять..


 
SergGG ©   (2007-03-30 09:47) [5]

>Dmitry_177   (30.03.07 09:22)
Если тебе нужно использовать FillChar...

Type
TCodes= Integer;
PCodes=^TCodes;

procedure TForm1.Button1Click(Sender: TObject);
var Codes:PCodes;
begin
GetMem(Codes, SizeOf(TCodes));
FillChar(Codes^, SizeOf(Codes), 0);
Codes^ := 212;
MessageBox(0, PChar(IntToStr(Codes^)), "", 0);
FreeMem(Codes, SizeOf(TCodes));
end;


 
Ketmar ©   (2007-03-30 12:21) [6]

на кол. что, справку отменили? там по dynamic arrays весьма немало текста... кажыдцо, пора опять мётлы раздавать... %-((


 
Dmitry_177   (2007-03-30 14:42) [7]

Мы ведиляем под массив память: SetLength(Codes, 1); а когда массив уже становится ненужным нужно ли освобождать память, которая была под него выделена? Как-нибудь так: FreeMem(Codes); ???


 
SergGG ©   (2007-03-30 15:01) [8]

>SetLength(Codes, 1) .... FreeMem(Codes); ???
Их нельзя связать.
См. [5]. Там нет SetLength


 
Loginov Dmitry ©   (2007-03-30 18:58) [9]

> Мы ведиляем под массив память: SetLength(Codes, 1); а когда
> массив уже становится ненужным нужно ли освобождать память,
> которая была под него выделена?


Как хочешь. Можешь освобождать, а можешь и не освобожать. Для освобождения памяти следует сделать следующее:
Code := nil;


 
Dmitry_177   (2007-04-02 11:17) [10]

А как можно из такого массива удалить какойнибудь элемент? Например будет он состоять из 5 элементов, а удалить к примеру 3?


 
Asail   (2007-04-02 11:33) [11]

ИМХО Никак.
Только смещением (т.е. 4-й в 3-й и 5-й в 4-й и т.д., потом SetLength(n-1))


 
VEZ   (2007-04-02 17:54) [12]


> А как можно из такого массива удалить какойнибудь элемент?
>  Например будет он состоять из 5 элементов, а удалить к
> примеру 3?


Имхо так

procedure TForm2.Button1Click(Sender: TObject);
var
 a: array of Word;
 i: Integer;
begin
 SetLength(a, 5);
 Label1.Caption:= "";
 Label2.Caption:= "";
 for i := 0 to Length(a) - 1 do
 begin
   a[i]:= i;
   Label1.Caption:= Label1.Caption + IntToStr(a[i]) + " ";
 end;
 // Remove 3th element
 MoveMemory(@a[3], @a[4], (Length(a)-3) * SizeOf(Word));
 SetLength(a, 5-1);
 // element has removed
 for i := 0 to Length(a) - 1 do
   Label2.Caption:= Label2.Caption + IntToStr(a[i]) + " ";
end;


 
Dmitry_177   (2007-04-02 18:55) [13]

Мне тут подсказали еще лучше способ =)

//удалить i-й элемент массива

move(codes[i+1],codes[i],(length(codes)-i-1)*sizeof(integer));
setlength(codes,length(codes)-1);


 
Asail   (2007-04-02 20:47) [14]


> VEZ   (02.04.07 17:54) [12]

> Имхо так

Ну, я и говорю - смещением...


> Dmitry_177   (02.04.07 18:55) [13]
> Мне тут подсказали еще лучше способ =)


Чем лучший и по сравнению с каким? Тот-же способ, что у VEZ.


 
Dmitry_177   (2007-04-02 23:05) [15]

да, но этот ИМХО быстрей..


 
MsGuns ©   (2007-04-02 23:16) [16]

Буря в стакане блин, - прав Кетмарь, метлы нужны



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

Форум: "Начинающим";
Текущий архив: 2007.04.22;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.042 c
2-1175269492
ditork
2007-03-30 19:44
2007.04.22
Закраска


10-1131727900
Георгий
2005-11-11 19:51
2007.04.22
Delphi+Excel


15-1174680887
iZEN
2007-03-23 23:14
2007.04.22
Онлайн Интервью с Ольгой Дергуновой


2-1175680793
Tifon
2007-04-04 13:59
2007.04.22
Радиальный градиент. Как создать в Делфи7?


2-1175755840
Мимопроходящий
2007-04-05 10:50
2007.04.22
Преобразование строки в вид %EA%BD...





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский