Что скрывается под указателем?

Вопросы программирования на Free Pascal, использования компилятора и утилит.

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

Ответить
Аватара пользователя
VirtUX
энтузиаст
Сообщения: 880
Зарегистрирован: 05.02.2008 09:52:19
Откуда: Крым, Алушта

Что скрывается под указателем?

Сообщение VirtUX »

Имеется некоторый типизированный указатель на запись. Допустим такой:

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

type
  AnyP = ^AnyRec;
  AnyRec = record
    ...
    Next: AnyP;
  end;
var
  P: AnyRec;

Связный список грузится из файла. Есно Next подхватывает какой-то левый адрес сохраненный в файл. То что Next <> nil говорит о том, что там что-то должно быть. Но как узнать есть-ли там уже чтот конкретное или это палец в небе? Т.е. как узнать левый это адрес или нет?
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

никак, это палец в небе.
зачем сохранять указатели в файл? если нужен только некст - его надо не сохранять, а восстанавливать при загоузке.
Аватара пользователя
*vmr
постоялец
Сообщения: 168
Зарегистрирован: 08.01.2007 00:46:07
Откуда: Киев
Контактная информация:

Сообщение *vmr »

Вместо указателя используй индекс в массиве(в смысле в файле храни индекс). При загрузке - делаешь фикс-ап
Аватара пользователя
VirtUX
энтузиаст
Сообщения: 880
Зарегистрирован: 05.02.2008 09:52:19
Откуда: Крым, Алушта

Сообщение VirtUX »

zub писал(а):если нужен только некст - его надо не сохранять, а восстанавливать при загоузке.

Вот тут меня и осенило :)

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

if Ofs(AnyP^.Next^) - Ofs(AnyP^) <> SizeOf(P) then {Палец в небе}
else {Реальные данные}

...или я не прав?

Добавлено спустя 10 минут 18 секунд:
Я ведь не реальный пример привел выше, а только для объяснения. Дело в том, что не всегда Next может быть инициализирован и восстановление данных производится не линейно, а "древовидно" на основе того, что:
- была ли ссылка из конкретного элемента связанного списка на другой (об этом говорит наличие или отсутствие какого-либо адреса в "Next");
- найдены-ли уже данные для указателя конкретного элемента или нет (об этом должен сказать или "Палец в небе", или "Реальные данные"), и если еще нет, то инициализировать указатель и присвоить данные;
- и другое...
При чем файл этот - нестандартная база и придумана не мной. А вот работать с ней мне как-то нуна.

Добавлено спустя 5 минут 57 секунд:
Хотя, наверное, правильней будет:

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

if ((Ofs(AnyP^.Next^) - Ofs(AnyP^)) mod SizeOf(P)) <> 0 then {Палец в небе}
else {Реальные данные}

Хотя и это не факт... млин... :?

Добавлено спустя 10 минут 7 секунд:
Вот, что пишет сам разработчик об этом файле:

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

{ Стpуктуpа записи файла CAS.RUL                                }
{ Размеp записи: 321 байт                                       }
{ ??? - значение поля на диске несущественно, но лучше обнулить }


const
      ListLimit =    15;

type  pCas      = ^CasType;

      ListType  = array [1..ListLimit] of pCas;

      CasType=    record
          {   1}    Group    :boolean;    { Пpизнак ветвь/лист (false/true) }
          {   4}    Parent   :pCas;       { Ссылка на ветвь-pодителя ???    }
          {  51}    Name     :string[50]; { Текст ветви или листа           }
          {   4}    BalloonL :longint;    { Пpизнак наличия баллона         }
          { 201}    BalloonS :string[200];{ Текст баллона                   }
          {15*4}    List     :ListType;   { ссылки на потомков              }
                  end;

При чем разница между смежными адресами не 321, а 172 (это я вычислил из сохраненных в файл адресов памяти);
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Хотя, наверное, правильней будет:
правильней так не будет. то что ты читаешь из файла - по любому указатель в никуда, сразу его в nil или фиксить.

если структура данных сложная ссылающаяся на саму себя, я бы пормимо данных сохранял в файл табличку соответствия старый адрес : позиция в файле, по ней фикся указатели при загрузке
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Менеджер памяти не гарантирует, то что при следующем запуске программы адреса будут выделятся такиеже как и при предыдыщем.

Добавлено спустя 40 секунд:
Так что смысла сохранять указатели на реальные данные в памяти нет.
Timid
постоялец
Сообщения: 290
Зарегистрирован: 21.11.2007 20:33:15

Сообщение Timid »

2 VirtUX: Советую "редуцировать" указатели в динамический массив, содержащий записи указанного типа. Заменить указатель на родителя на индекс в массиве. Затем уже сохранять.

Перебросить дерево в массив просто с использованием рекурсивного обхода.

Насчет размещения в памяти "смежных" узлов.
Совсем не обязательно, что они будут идти рядом. Запись никогда не хранится совместно. Менеджер памяти размещает в записи лишь указатели на реальные области памяти, отданные под переменные.
Михаил Крамер
новенький
Сообщения: 73
Зарегистрирован: 08.02.2008 13:26:40

Сообщение Михаил Крамер »

Эм, односвязный список всегда проходится только в обном направлении - от первого элемента к последнему. Никакого дерева и не видать. Что такое "ссылка на ветвь родитель" в приведённом примере - непонятно. Хранить указатели в файле - бесполезно и не нужно, надо придумать другой способ сохранить структуру дерева, если оно всё же дерево, в файле..
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

чем плох XML?
Михаил Крамер
новенький
Сообщения: 73
Зарегистрирован: 08.02.2008 13:26:40

Сообщение Михаил Крамер »

О, ксати, в приведённом примере (большом) действительно дерево. До меня дошло.
xdsl
постоялец
Сообщения: 131
Зарегистрирован: 15.01.2009 12:49:03

Сообщение xdsl »

Если в файле перед каждым элементом сохранять еще и указатель на него, то впоследствии при чтении структура будет ввостановима. Хотя для дерева это конечно бессмысленное действо, т.к. проще релизовать корректный, обратимый алгоритм записи-чтения.
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

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

Вы не правы! Нельзя просто читать указатели без выделения памяти. При проуедуре выделения памяти нет горантии, что указатель прочитанный будет соответсвовать выделенному!
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

Mr.Smart
Не предлагается использовать указатель голым образом :)

Утверждается, что если с каждой записываемой структурой сохранить указатель на нее, то при чтении можно будет разобраться как эти структуры были связаны. Далее выделяется память заново и все указатели проставляются.
Аватара пользователя
VirtUX
энтузиаст
Сообщения: 880
Зарегистрирован: 05.02.2008 09:52:19
Откуда: Крым, Алушта

Сообщение VirtUX »

Дож писал(а):Mr.Smart
Не предлагается использовать указатель голым образом :)

Утверждается, что если с каждой записываемой структурой сохранить указатель на нее, то при чтении можно будет разобраться как эти структуры были связаны. Далее выделяется память заново и все указатели проставляются.
Согласен.
В данном случае (в дереве) поле List, указывающее на потомков расскажет сколько их было. Т.е.

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

while List > 0 do
. Затем переходим к следующей ветке (List[n]) и проверяем были-ли у нее свои ветки или нет. Если нет, то переходим к соседней. И т.д.
Ответить