Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.11.08;
Скачать: CL | DM;

Вниз

array [0..0] of ...   Найти похожие ветки 

 
Прима   (2009-09-18 12:49) [0]


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;


В чем я не прав ? Необходимо заранее указывать размер массива?
Тогда как ?

Спасибо !


 
Прима   (2009-09-18 12:54) [1]


 Q.B:=1;
 SetLength(Q.Q,2); <=Incompatible types
 Q.Q[0].S1:=1;


 
Прима   (2009-09-18 12:56) [2]

Пардон. Разобрался.
Вот решение : TMArr = array of TElem;


 
Юрий Зотов ©   (2009-09-18 13:01) [3]

> Прима   (18.09.09 12:49)  

>  Необходимо заранее указывать размер массива?

Размер статического массива указывается при его объявлении и не может быть изменен. Вы объявили статисеский массив, который содержит один элемент с индексом 0, поэтому Q.Q[1] дает ошибку.

> Тогда как ?

Используйте либо динамический массив (см. в справке Dynamic arrays), либо указатель на статический массив (сначала выделив под него память, конечно). Первый способ, похоже, будет проще.


 
Прима   (2009-09-18 13:18) [4]

2 Юрий Зотов ©   (18.09.09 13:01) [3]

Спасибо

.
>  либо указатель на статический массив (сначала выделив под
> него память, конечно).


Хочу разобраться для себя. Можно подробнее и кодом ?
GetMem(Q.Q,SizeOf(TElem)*2);
Ибо даже выделить память пока не получается


 
Anatoly Podgoretsky ©   (2009-09-18 13:24) [5]


> Прима   (18.09.09 13:18) [4]

Для статических массивов память тоже выделяется статически, через указание размерности в типа.


 
Прима   (2009-09-18 13:26) [6]

2 Anatoly Podgoretsky ©   (18.09.09 13:24) [5]
> Для статических массивов память тоже выделяется статически,
>  через указание размерности в типа.


Пардон, но я не понял. Можно ли кодом ?


 
Anatoly Podgoretsky ©   (2009-09-18 13:30) [7]

Можно

>  TMArr = array [1..11] of TElem;

Вот тут выделена память по 11 элементов типа TElem


 
Прима   (2009-09-18 13:35) [8]

Это понятно.
Я хочу для себя разобраться как работать с [0..0]

Насколько я понимаю, нужно завести новую переменную. И указать ей размер будующего массива. А далее не понятно.

 var  P:Pointer;
begin
 GetMem(P,SizeOf(TElem)*2);
 Q.Q сопоставить с P как-то


 
Anatoly Podgoretsky ©   (2009-09-18 13:41) [9]

> Прима  (18.09.2009 13:35:08)  [8]

Работать с [0..0] идеологически неправильно, работай с [0..MaxInt]


 
Anatoly Podgoretsky ©   (2009-09-18 13:44) [10]

P: ^TMArr;

Но в наше время нужды в этом нет, начиная с Д4 есть динамические массивы.


 
Юрий Зотов ©   (2009-09-18 14:07) [11]

> Прима   (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;


 
Прима   (2009-09-18 14:36) [12]

Спасибо.


 
Anatoly Podgoretsky ©   (2009-09-18 15:03) [13]

> Юрий Зотов  (18.09.2009 14:07:11)  [11]

Так у него проблема как раз с
TMArr = packed array [0..0] of TElem;
Массив размером на 1 элемент и проверка диапазонов ругается на это.
Эта техника из СИ и некоторое время успешнь использовалась в Паскале.
Правильнее указать диапазон с запасом, чем с недостатком.


 
Прима   (2009-09-21 15:09) [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;


 
Palladin ©   (2009-09-21 16:12) [15]


> Прима   (21.09.09 15:09) [14]

Так и кричит благим матом? "неработаю" мол...


 
Юрий Зотов ©   (2009-09-21 16:40) [16]

> Прима   (21.09.09 15:09) [14]

А как Вы думаете, зачем понадобилась функция GetElem?


 
Sapersky   (2009-09-21 17:56) [17]

ИМХО не нужна она там, разве что для контроля индексов. Проще прямо обращаться к элементам, иначе зачем вся эта возня с объявлением типов.
А если уж использовать функцию, то возвращать она должна указатель (PElem), или для модификации элементов должна быть отдельная функция SetElem.


 
Sha ©   (2009-09-21 20:29) [18]

> Anatoly Podgoretsky ©   (18.09.09 15:03) [13]
> Правильнее указать диапазон с запасом, чем с недостатком.

Это хоть обойти можно, а вот отрицательный индекс (константу) написать не дают.


 
Юрий Зотов ©   (2009-09-21 20:48) [19]

> Sapersky   (21.09.09 17:56) [17]

1. Она нужна, чтобы обмануть "Range check error".
2. Что она должна возвращать - это дело вкуса.
3. Вот SetElem здесь как раз будет лишней.


 
Прима   (2009-09-21 21:53) [20]


> Так и кричит благим матом? "неработаю" мол...


Нет...она работает, но возвращаемые значения не те.


 
Sapersky   (2009-09-21 23:40) [21]

Она нужна, чтобы обмануть "Range check error".

Чем обманывать, так проще вообще отключить (хотя бы локально, $R-). Быстрее работать будет.

Что она должна возвращать - это дело вкуса.

Вообще да, но в примере [11] - нет. Вы же там пытаетесь задать элементам значения через GetItem. Естественно, ничего не задаётся, поскольку всё пишется в возвращаемую переменную, а не в массив.


 
Германн ©   (2009-09-22 02:05) [22]


> Прима   (18.09.09 13:35) [8]
>
> Это понятно.
> Я хочу для себя разобраться как работать с [0..0]

А не надо с этим способом объявления "разбираться". Надо его не использовать никогда.


 
Sapersky   (2009-09-22 03:59) [23]

Иногда бывает удобно, например, если некий API возвращает нетипизированный указатель, но мы точно знаем, что там массив - можно откастить к массиву и работать с относительным комфортом. Также можно "вырезать" фрагмент массива без копирования, просто сдвинув указатель.

Хотя я в большинстве случаев использую дин. массивы, в основном потому, что их содержимое можно посмотреть при отладке.


 
Anatoly Podgoretsky ©   (2009-09-22 09:51) [24]

> Sapersky  (22.09.2009 03:59:23)  [23]

Хорошо, но зачем для этого 0..0, а не 0..много


 
Sapersky   (2009-09-22 13:08) [25]

Ну пусть будет 0..много, не принципиально. Хотя несколько громоздко получается, чтобы получить макс. размер приходится писать что-то вроде [0..(MaxInt div SizeOf(TElement))-1]. 0..MaxInt-1 компилятор не пропускает, слишком большой размер типа (кроме массива байтов, ест-но).


 
Leonid Troyanovsky ©   (2009-09-22 13:26) [26]


> Sapersky   (22.09.09 13:08) [25]

> писать что-то вроде [0..(MaxInt div SizeOf(TElement))-1].

const
 MaxElem = MaxInt div SizeOf(TElem);

--
Regards, LVT.


 
Anatoly Podgoretsky ©   (2009-09-22 13:38) [27]

> Sapersky  (22.09.2009 13:08:25)  [25]

Ничего писать не надо, в системе уже объявлены нужные константы.



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

Текущий архив: 2009.11.08;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.015 c
15-1252515306
Rule
2009-09-09 20:55
2009.11.08
Книга по (для) рисования.


15-1252512460
Kostafey
2009-09-09 20:07
2009.11.08
Синхронизация Mercurial-репозитариев с ограничением


15-1252842870
_Андрей
2009-09-13 15:54
2009.11.08
инет в Viste


15-1252568155
tesseract
2009-09-10 11:35
2009.11.08
Репетиция дня пргораммиста


2-1253176698
Руслан
2009-09-17 12:38
2009.11.08
ПОМОГИТЕ