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

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

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

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

Сообщение vvvch »

AlphaBlend
Не обращайте внимания, ему нужно действительно использовать что, то типа TList. Возможно мы не понимаем сути его задачи. На моей практике это часто бывает. Пусть сам разбирается.
CRobin
постоялец
Сообщения: 145
Зарегистрирован: 26.01.2016 11:15:39

Сообщение CRobin »

vvvchты реально до сих пор не понял "сути задачи"? Открой глаза, прочитай название темы, в которую пишешь. Если это не стеб, то ситуация просто клиническая.
resident
энтузиаст
Сообщения: 605
Зарегистрирован: 13.03.2013 16:58:51

Сообщение resident »

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

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

Сообщение vvvch »

CRobin
Во первых, не "тыкай" мне, я на Вы разговаривал. Во-вторых если просишь помощи, научись не хамить!
CRobin
постоялец
Сообщения: 145
Зарегистрирован: 26.01.2016 11:15:39

Сообщение CRobin »

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

Сообщение vvvch »

CRobin а может это Вы чего-то не понимаете, что Вам хотят сказать? (Что более вероятно!) Ну ничего, со временем дойдёт...
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

ИМХО, для таких дел проще использовать индексируемые контейнеры без понятия "диапазон ключей" - наприклад хэш-таблицы.
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

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 вернёт указатель на элемент. И указатель будет правильным, но только до следующего изменения нижней границы.
CRobin
постоялец
Сообщения: 145
Зарегистрирован: 26.01.2016 11:15:39

Сообщение CRobin »

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

Сообщение скалогрыз »

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.
CRobin
постоялец
Сообщения: 145
Зарегистрирован: 26.01.2016 11:15:39

Сообщение CRobin »

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


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

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

Код: Выделить всё

type TMyArray(a,b:integer) = array [a..b] of elem; 
var PMyArray = TMyArray(222,333);


правильно ли я понимаю что уже это не возможно?
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

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 писал(а):раньше Паскаль поддерживал такой синтаксис


а раньше это когда?
CRobin
постоялец
Сообщения: 145
Зарегистрирован: 26.01.2016 11:15:39

Сообщение CRobin »

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

последний раз на нем писал когда у меня был 486dx
скалогрыз
долгожитель
Сообщения: 1804
Зарегистрирован: 03.09.2008 02:36:48

Сообщение скалогрыз »

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

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

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

Может какой-нить Mircosoft Pascal?
Последний раз редактировалось скалогрыз 06.07.2016 21:40:39, всего редактировалось 1 раз.
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

CRobin

Код: Выделить всё

const a = 22222222222222;
         b = 22222222222333;
var dic : array[a..b] of TEntry;

Больны какраз вы. Лекарство в постах скалогрыз
Ответить