![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
array [0..0] of ... [D7]
Прима © (2009-09-18 12:49:00)
type
TElem = packed record
S1:Byte;
S2:Byte;
D1:DWord;
end;
TMArr = array [0..0] of TElem;
TFuck = record
B:Byte;
Q:TMArr;
end;
procedure TForm1.Button1Click(Sender: TObject);
var Q:TFuck;
I:Integer;
begin
Q.B:=1;
Q.Q[0].S1:=1;
Q.Q[0].S2:=1;
Q.Q[0].D1:=1;
Q.Q[1].S1:=2; <=Constant expression violates subrange bounds
Q.Q[1].S2:=2;
Q.Q[1].D1:=2;
//
for I:=0 to Length(Q.Q)-1 do
begin
Memo1.Lines.Add(Format('%d %d',[Q.Q[I].S1, Q.Q[I].S2]));
end;
end;
В чем я не прав ? Необходимо заранее указывать размер массива?
Тогда как ?
Спасибо !
Anatoly Podgoretsky (2009-09-22 13:38:00) [1]> Sapersky (22.09.2009 13:08:25) [25]
Ничего писать не надо, в системе уже объявлены нужные константы.
Leonid Troyanovsky (2009-09-22 13:26:00) [2]
> Sapersky (22.09.09 13:08) [25]
> писать что-то вроде [0..(MaxInt div SizeOf(TElement))-1].
const
MaxElem = MaxInt div SizeOf(TElem);
--
Regards, LVT.
Sapersky (2009-09-22 13:08:00) [3]Ну пусть будет 0..много, не принципиально. Хотя несколько громоздко получается, чтобы получить макс. размер приходится писать что-то вроде [0..(MaxInt div SizeOf(TElement))-1]. 0..MaxInt-1 компилятор не пропускает, слишком большой размер типа (кроме массива байтов, ест-но).
Anatoly Podgoretsky (2009-09-22 09:51:00) [4]> Sapersky (22.09.2009 03:59:23) [23]
Хорошо, но зачем для этого 0..0, а не 0..много
Sapersky (2009-09-22 03:59:00) [5]Иногда бывает удобно, например, если некий API возвращает нетипизированный указатель, но мы точно знаем, что там массив - можно откастить к массиву и работать с относительным комфортом. Также можно "вырезать" фрагмент массива без копирования, просто сдвинув указатель.
Хотя я в большинстве случаев использую дин. массивы, в основном потому, что их содержимое можно посмотреть при отладке.
Германн (2009-09-22 02:05:00) [6]
> Прима (18.09.09 13:35) [8]
>
> Это понятно.
> Я хочу для себя разобраться как работать с [0..0]
А не надо с этим способом объявления "разбираться". Надо его не использовать никогда.
Sapersky (2009-09-21 23:40:00) [7]Она нужна, чтобы обмануть "Range check error".
Чем обманывать, так проще вообще отключить (хотя бы локально, $R-). Быстрее работать будет.
Что она должна возвращать - это дело вкуса.
Вообще да, но в примере [11] - нет. Вы же там пытаетесь задать элементам значения через GetItem. Естественно, ничего не задаётся, поскольку всё пишется в возвращаемую переменную, а не в массив.
Прима (2009-09-21 21:53:00) [8]
> Так и кричит благим матом? "неработаю" мол...
Нет...она работает, но возвращаемые значения не те.
Юрий Зотов (2009-09-21 20:48:00) [9]> Sapersky (21.09.09 17:56) [17]
1. Она нужна, чтобы обмануть "Range check error".
2. Что она должна возвращать - это дело вкуса.
3. Вот SetElem здесь как раз будет лишней.
Sha (2009-09-21 20:29:00) [10]> Anatoly Podgoretsky © (18.09.09 15:03) [13]
> Правильнее указать диапазон с запасом, чем с недостатком.
Это хоть обойти можно, а вот отрицательный индекс (константу) написать не дают.
Sapersky (2009-09-21 17:56:00) [11]ИМХО не нужна она там, разве что для контроля индексов. Проще прямо обращаться к элементам, иначе зачем вся эта возня с объявлением типов.
А если уж использовать функцию, то возвращать она должна указатель (PElem), или для модификации элементов должна быть отдельная функция SetElem.
Юрий Зотов (2009-09-21 16:40:00) [12]> Прима (21.09.09 15:09) [14]
А как Вы думаете, зачем понадобилась функция GetElem?
Palladin (2009-09-21 16:12:00) [13]
> Прима (21.09.09 15:09) [14]
Так и кричит благим матом? "неработаю" мол...
Прима (2009-09-21 15:09:00) [14]2 Юрий Зотов © (18.09.09 14:07) [11]
Я конечно извиняюсь, но пример не работает.
Вывожу так :
for I:=0 to 9 do
with R.Q[I] do
begin
Memo1.Lines.Add(Format('%d %d %d',[I,S1,S2]));
end;
Anatoly Podgoretsky (2009-09-18 15:03:00) [15]> Юрий Зотов (18.09.2009 14:07:11) [11]
Так у него проблема как раз с
TMArr = packed array [0..0] of TElem;
Массив размером на 1 элемент и проверка диапазонов ругается на это.
Эта техника из СИ и некоторое время успешнь использовалась в Паскале.
Правильнее указать диапазон с запасом, чем с недостатком.
Прима (2009-09-18 14:36:00) [16]Спасибо.
Юрий Зотов (2009-09-18 14:07:00) [17]> Прима (18.09.09 12:49)
type
TElem = packed record
S1:Byte;
S2:Byte;
D1:DWord;
end;
PElem = ^TElem
TMArr = packed array [0..0] of TElem;
PMArr = ^TMArr;
TRec = record
B: Byte;
Q: PMArr;
end;
function GetElem(R: TRec, Index: integer): TElem;
begin
Result := PElem(Cardinal(R.Q) + Index * SizeOf(TElem))^
end;
procedure TForm1.Button1Click(Sender: TObject);
var
R: TRec;
i: integer;
begin
R.B:=1;
GetMem(R.Q, 10 * SizeOf(TElem)); // Выделили память под 10 элементов
try
for i := 0 to 9 do
with GetElem(R, i) do
begin
S1 := i;
S2 := i;
D1 := i;
end
finally
FreeMem(R.Q, 10 * SizeOf(TElem));
end
end;
Anatoly Podgoretsky (2009-09-18 13:44:00) [18]P: ^TMArr;
Но в наше время нужды в этом нет, начиная с Д4 есть динамические массивы.
Anatoly Podgoretsky (2009-09-18 13:41:00) [19]> Прима (18.09.2009 13:35:08) [8]
Работать с [0..0] идеологически неправильно, работай с [0..MaxInt]
Прима (2009-09-18 13:35:00) [20]Это понятно.
Я хочу для себя разобраться как работать с [0..0]
Насколько я понимаю, нужно завести новую переменную. И указать ей размер будующего массива. А далее не понятно.
var P:Pointer;
begin
GetMem(P,SizeOf(TElem)*2);
Q.Q сопоставить с P как-то