Как задать нижнюю границу массива динамически?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Re: Как задать нижнюю границу массива динамически?

Сообщение vvvch » 06.07.2016 20:29:11

AlphaBlend
Не обращайте внимания, ему нужно действительно использовать что, то типа TList. Возможно мы не понимаем сути его задачи. На моей практике это часто бывает. Пусть сам разбирается.
Аватара пользователя
vvvch
постоялец
 
Сообщения: 105
Зарегистрирован: 26.04.2013 11:05:39
Откуда: г.Боровичи, Новг. обл.

Re: Как задать нижнюю границу массива динамически?

Сообщение CRobin » 06.07.2016 20:36:02

vvvchты реально до сих пор не понял "сути задачи"? Открой глаза, прочитай название темы, в которую пишешь. Если это не стеб, то ситуация просто клиническая.
CRobin
постоялец
 
Сообщения: 145
Зарегистрирован: 26.01.2016 12:15:39

Re: Как задать нижнюю границу массива динамически?

Сообщение resident » 06.07.2016 20:39:53

AlphaBlend писал(а):Вам не только на блюдечке все п одали выше , но еще и салфеточку повязали и даже разжевали :mrgreen:

И не только выше, на форуме точно такая же тема поднималась совсем недавно.
resident
энтузиаст
 
Сообщения: 605
Зарегистрирован: 13.03.2013 16:58:51

Re: Как задать нижнюю границу массива динамически?

Сообщение vvvch » 06.07.2016 20:44:49

CRobin
Во первых, не "тыкай" мне, я на Вы разговаривал. Во-вторых если просишь помощи, научись не хамить!
Аватара пользователя
vvvch
постоялец
 
Сообщения: 105
Зарегистрирован: 26.04.2013 11:05:39
Откуда: г.Боровичи, Новг. обл.

Re: Как задать нижнюю границу массива динамически?

Сообщение CRobin » 06.07.2016 20:50:53

vvvch при столь очевидной и простой формулировке задачи вас не беспокоит, что вы до сих пор ее не поняли, исписав две страницы ответов. Зато беспокоит что я обращаюсь к вам на "ты". Это поразительно.
CRobin
постоялец
 
Сообщения: 145
Зарегистрирован: 26.01.2016 12:15:39

Re: Как задать нижнюю границу массива динамически?

Сообщение vvvch » 06.07.2016 20:56:21

CRobin а может это Вы чего-то не понимаете, что Вам хотят сказать? (Что более вероятно!) Ну ничего, со временем дойдёт...
Аватара пользователя
vvvch
постоялец
 
Сообщения: 105
Зарегистрирован: 26.04.2013 11:05:39
Откуда: г.Боровичи, Новг. обл.

Re: Как задать нижнюю границу массива динамически?

Сообщение debi12345 » 06.07.2016 21:12:09

ИМХО, для таких дел проще использовать индексируемые контейнеры без понятия "диапазон ключей" - наприклад хэш-таблицы.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Как задать нижнюю границу массива динамически?

Сообщение скалогрыз » 06.07.2016 21:15:26

CRobin писал(а):скалогрыз не уверен, но есть ощущение, что такое все же можно сделать через динамические константы и указатели. В случае с объектом я не могу передать указатель на конкретное поле записи, насколько я понимаю, по типу такого


Объект использовать не обязательно, но очень удобно, т.к. он прячет (инкапсулирует) дополнительные переменные, необходимые для отслеживания нижней границы, а так же всю рутину которая возникает в случае изменения нижней границы.

Указатель получить на конкертное поле записи можно:
Код: Выделить всё
type
  TEntryArray = class(TObject)
     ...
     function GetElementPtr(i: integer): PEntry;
  end;

function TEntryArray.GetElementPtr(i: integer): PEntry;
begin
  //todo: sanity check, return nil, if i is invalid
  Result:=@data[i-flow];
end;


на выходе получаем код:
Код: Выделить всё
  e := @data.GetElementPtr(i)^.field;

может быть не очень красиво, но зато работает. Тут можно ещё задаться вопросом что это за тип такой TEntry.

(Кстати, отличный пример, где дженерики хорошо бы подошли, Дож ;) )

Если TEntry это какой-нить record, то следует помнить, что GetLEmentPtr вернёт указатель на элемент. И указатель будет правильным, но только до следующего изменения нижней границы.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Как задать нижнюю границу массива динамически?

Сообщение CRobin » 06.07.2016 21:41:04

скалогрыз адрес элемента массива в памяти можно найти отсчитав от адреса массива i*SizeOf(TEntry), затем, имея адрес можно получить значение. Что и происходит, при обращении к элемента массива по индексу начинающемуся с 0. Но в случае, если массив объявлен статически с использованием перечисления или через указание интервал [A..B], тогда так не получается. Это означает, что где то в памяти находится значение "отступа", которое равно А. Вопрос - можно ли изменить в памяти это значение А для того чтоб сделать в индексе смещение? Например задав компилятору определенные директивы, которые позволят вмешиваться в способ хранения массива.
CRobin
постоялец
 
Сообщения: 145
Зарегистрирован: 26.01.2016 12:15:39

Re: Как задать нижнюю границу массива динамически?

Сообщение скалогрыз » 06.07.2016 21:55:05

CRobin писал(а):Но в случае, если массив объявлен статически с использованием перечисления или через указание интервал [A..B], тогда так не получается. Это означает, что где то в памяти находится значение "отступа", которое равно А.

нет, именно так и получается. В памяти значние "A" для статических массивов не хранится - это лишний расход памяти.
Во время компиляции, компилятор знает об отступе "A", и все обращения к статическому массиву преобразуются с учётом этого отступа.
Например
Код: Выделить всё
procedure Test;
var
  a: array [2..4] of integer;
begin
  a[2]:=5;
  a[3]:=6;
  writeln(a[3]);
end;

begin
  Test;
end.

В коде написано writelN(a[3]);
А на самом деле компилятор преобразует этот вызов в writeln(a[1]);... потому что для компилятора массив [2..4] (условно) становится [0..2].

Значение "А" так же не хранится для динамических массивов - они просто всегда начинаются с 0.
Дополнительных директив для управления начальным индексом массива нет.

Рекомендую скомпилировать следующий код, с директировой -al, чтобы получить ассебмлерный код. И сравнить процедуры Test и Test2
Код: Выделить всё
procedure Test;
var
  a: array [2..4] of integer;
begin
  a[2]:=5;
  a[3]:=6;
  writeln(a[3]);
end;

procedure Test2;
var
  a: array [0..2] of integer;
begin
  a[0]:=5;
  a[1]:=6;
  writeln(a[1]);
end;

begin
  Test;
  Test2;
end.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Как задать нижнюю границу массива динамически?

Сообщение CRobin » 06.07.2016 22:14:55

скалогрыз писал(а):Во время компиляции, компилятор знает об отступе "A", и все обращения к статическому массиву преобразуются с учётом этого отступа.


Все так. Но ведь обращение к элементу по индексу я могу делать, например, вводя ключ с клавиатуры. Компилятор не знает что именно я введу, а это значит ему нужно будет отнять отступ А для того чтоб получить нужный элимент, иначе никак. Это значит, что где то в памяти все же этот отступ хранится.

Добавлено спустя 6 минут 53 секунды:
раньше Паскаль поддерживал такой синтаксис

Код: Выделить всё
type TMyArray(a,b:integer) = array [a..b] of elem;
var PMyArray = TMyArray(222,333);


правильно ли я понимаю что уже это не возможно?
CRobin
постоялец
 
Сообщения: 145
Зарегистрирован: 26.01.2016 12:15:39

Re: Как задать нижнюю границу массива динамически?

Сообщение скалогрыз » 06.07.2016 22:26:47

CRobin писал(а):Компилятор не знает что именно я введу, а это значит ему нужно будет отнять отступ А для того чтоб получить нужный элимент, иначе никак. Это значит, что где то в памяти все же этот отступ хранится

Он не хранится в памяти, отступ А будет внесён непосредственно в код обращения к элементу.
Вот код.
Код: Выделить всё
{$mode delphi}
uses Classes, SysUtils;
var
  a: array [10..20] of integer;
  s: string;
  i: integer;
  k: integer;
begin
  for i:=low(a) to high(a) do
    a[i]:=i;
 
  readln(s);
  while s<>'' do begin
    i:=StrToIntDef(s,-1);
    if (i>=low(a)) and (i<=high(a)) then begin
      k:=a[i];
      writeln(k); 
    end;
    readln(s);
  end;
end.


Компилируем с ассемблером (fpc -as -Amasm test.pas)
Результат:
Код: Выделить всё
; [16] k:=a[i];
      mov   eax,dword ptr [U_P$PROGRAM_I]
      mov   eax,dword ptr [U_P$PROGRAM_A+eax*4-40]
      mov   dword ptr [U_P$PROGRAM_K],eax

на (не)человечьем языке это звучит так
1) возьми переменную I
2) помнож значение на 4, и вычти 40 (размер integer-а - это 4 байта, а массив начинается с 10-го элемента. 4*10 = 40)
3) возьми 4-х байтное значение по указанному отступу и запиши в переменную K.

Отступ "А" - стал частью кода, а не отдельной переменной в памяти.

как я уже писал в другой теме, массивы вещь - низкоуровневая. Очень удобная для внутренней реализации, но не всегда подходит в качестве интерфейса :)

Добавлено спустя 6 минут 16 секунд:
CRobin писал(а):раньше Паскаль поддерживал такой синтаксис


а раньше это когда?
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Как задать нижнюю границу массива динамически?

Сообщение CRobin » 06.07.2016 22:34:23

скалогрыз писал(а):а раньше это когда?

последний раз на нем писал когда у меня был 486dx
CRobin
постоялец
 
Сообщения: 145
Зарегистрирован: 26.01.2016 12:15:39

Re: Как задать нижнюю границу массива динамически?

Сообщение скалогрыз » 06.07.2016 22:35:03

CRobin писал(а):последний раз на нем писал когда у меня был 486dx

возможно. А что за паскаль такой?
На моём 486, Turbo Pascal 7.0 и 5.0 такого не разрешали.

я точно знаю, как такое можно на Си написать!

Может какой-нить Mircosoft Pascal?
Последний раз редактировалось скалогрыз 06.07.2016 22:40:39, всего редактировалось 1 раз.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Как задать нижнюю границу массива динамически?

Сообщение zub » 06.07.2016 22:40:01

CRobin
Код: Выделить всё
const a = 22222222222222;
         b = 22222222222333;
var dic : array[a..b] of TEntry;

Больны какраз вы. Лекарство в постах скалогрыз
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Пред.След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 232

Рейтинг@Mail.ru