Форум: "Начинающим";
Текущий архив: 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