Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2002.12.02;
Скачать: [xml.tar.bz2];

Вниз

Что такое Самоадресуемая запись?   Найти похожие ветки 

 
Tano   (2002-11-18 02:20) [0]

Насколько я понял, нельзя создать тип - массив записей (и тем более указатель на это).
type
TFieldID = record
Tp :TNodeType;
Offs :Integer;
HD :THD;
end;
TFieldsID = array[0..cMaxFieldsCount] of TFieldID;
pTFieldsID = ^TFieldsID; <- Error 59: "TFieldsID" is not a type identifier


при этом
var
FieldsID :array[0..cMaxFieldsCount] of TFieldID;

имеет право на существование, а
var
FieldsID :TFieldsID;

уже нет.
Компилятор разрешает объявление типа "массив записей", но как его использовать?

В моем карманном справочнике упоминается "Самоадресуемая запись", но "поскольку в книге не используются, рекомендуем [1] и [3]...".
Если кто знает, хотя бы подскажите ключевые слова на английском (все что могло прийти в голову уже перебрал и в Helpe и на форуме).

Thanks!


 
ЮЮ   (2002-11-18 04:53) [1]

А почему бы просто не
TFieldsID = array of TFieldID;
и
var
FieldsID :TFieldsID;
имеет право на существование, и FieldsID - это только указатель
Правда, придётся работать аккуратно:
Устанавливать длину массива SetLength(FieldsID, xxx), при работе
проверять диапазон Low(FieldsID), Hogh(FieldsID) и длину Length(FieldsID)


 
MBo   (2002-11-18 06:16) [2]

>Tano
Все написанные тобой объявления совершенно корректны и проходят компиляцию.


 
Tano   (2002-11-18 07:52) [3]


> MBo © (18.11.02 06:16)

Синтаксически корректны, спору нет, но "Error 59..." - не плод моего больного воображения.


> ЮЮ © (18.11.02 04:53)

Не подходит


 
MBo   (2002-11-18 08:02) [4]

>Tano
у меня все это прекрасно компилируется в D5, хотя сомнений и так не было. Попробуй, что ли, объявление pTFieldsID раньше TFieldsID поставить


 
AngeL B.   (2002-11-18 10:25) [5]


> 2 Tano:

Все написаное правильно и проходит компиляцию.
Проверь правильность написания всего. Возможна опечатка.


 
Sergic   (2002-11-18 20:57) [6]

Самоадресуемая запись это такая вот штука:

type
PRec=TRec
TRec=record
ID:longint;
Next:PREc;
end;



 
Tano   (2002-11-18 21:04) [7]

Дело в том, что у меня была в записи еще и переменная String[118]:
TFieldID = record
Tp :TNodeType;
Offs :Integer;
HD :THD; //THD = Integer;
Name :String[118];
end;
TFieldsID = array[0..cMaxFieldsCount] of TFieldID;
pTFieldsID = ^TFieldsID;

Извеняюсь, наверное надо было сразу вписать, но мне показалось, что смысл от этого не изменится. Ан нет!
Ведь строка, которая в записи имеет фиксированный размер 128 байт. Какая разница компилятору, для каких структур считать адреса ???
Без строки действительно компилируется.

> > ЮЮ © (18.11.02 04:53)
Простите за лаконичность (очень спешил). Мне нужно объявить указатель на массив записей, который можно наложить на динамически выделяемую область памяти. Указанный Вами метод я первоначально и использовал, но постепенно от него возникло мелких сложностей больше, чем преимуществ.
Сейчас я вручную вычисляю адрес i-того элемента и накладываю на него указатель на тип record. Работает нормально, только выглядит коряво.

И все-же, кто-нибудь знает о Самоадресуемой записи? Мне уже просто становиться интересно.


 
Tano   (2002-11-18 21:11) [8]


> Sergic (18.11.02 20:57)

Это по виду элемент динамического списка, только PRec=^TRec.
Если Вы уверены, что это и есть загадочная самоадресуемая запись, то я разочарован :(. Thanks!


 
Tano   (2002-11-18 21:13) [9]

Поправка к моему сообщению (18.11.02 21:04): не строка размера 128 байт, а вся запись выровнена на 128 байт.


 
Walker   (2002-11-19 01:38) [10]

to Tano
попробуй написать так

Name: ShortString[118]



 
Tano   (2002-11-19 03:25) [11]

К сожалению, такое определение неверно.
ShortString - строка заготовленных 255 символов (и 0-й байт - длина), только в String[n] можно указать точный максимальный размер строки.


 
MBo   (2002-11-19 06:23) [12]

Строка не мешает, все по-прежнему компилируется (кстати, объявленная таким образом - она является Shortstring)?


 
Walker   (2002-11-19 06:27) [13]

to MBo
вот как раз X(ИКС) его знает. Только помню что однажды, когда использовал типизированные файлы, а в качестве записи - record, одним полем которым был String[n] - компилятор выдавал ошибку. Я заменил String на ShortString - всё заработало.


 
Tano   (2002-11-19 10:06) [14]

Насчет своего последнего мессэджа - уверен (это написано в Helpe).

Кое-что проверил. Странноватая картина:
Мой массив записей был размерности [0..cMaxFieldsCount], где
const
cMaxFieldsCount = (MaxInt div 128); {= 1 6 777 215}
так не работает, а если записать
const
cMaxFieldsCount = 1 5 777 215;
то работает.
В общем, на успешность компиляции влияет числовое значение размерности. Странно, что выдается ошибка 59 (идентефикатор не является типом).
Я подобрал число, являющееся границей для моего случая (16 268 814) - единицей больше и возникает ошибка.
Изначально константу я считал как предельное теоретически возможное значение из расчета адресуемости 2Gb памяти.

В общем-то вопрос прояснился в отношении того как надо делать, но по поводу причины возникновения ошибки - подобранную константу не пойму (она меньше на 500kb чем 2Gb div 128).

Кстати, если просто взять ОЧЕНЬ большую константу (из области допустимых Int64), то пишет ошибку "Требуется перечисляемый тип" - вот это понять и предвидеть можно.


 
han_malign   (2002-11-19 10:46) [15]

Во первых: Static array types are denoted by constructions of the form

array[indexType1, ..., indexTypen] of baseType

where each indexType is an ordinal type whose range does not exceed 2GB.

2GB=$80000000=2147483648, а твой массив получается 16777215*130=2181037950 - коментарии излишни.

Во вторых: самоадресуемая запись - неверный термин, есть самоадресуемый тип, пример приводился выше. Используется для создания связных списков. Примерно так Item<i+1> == Item .Next, при этом возмжен только последовательный доступ к елементам, немедленный по индексу невозможен. На таком же принципе строятся деревья, стеки, кольцевые списки, двусвязные списки, сети.

В третих: при {$R-}(по умолчанию Range checking отключен) достаточно
type
TFieldsID = array[0..0] of TFieldID;
PFieldsID = ^TFieldsID;
var _pFiledsID: PFieldsID;
begin
getMem(_pFiledsID,sizeof(TFiledsID)*N);
if(_pFiledsID<>nil)then begin//Memory allocated
................
with _pFiledsID[i] do ...
................
FreeMem(_pFiledsID);
end;
end;

- стринги здесь не причем просто в описании типа ты захотел больше памяти чем тебе может выделить Delphi.(в 16-битном Delphi не прошло бы даже array[0..65535]of byte, только array[0..65519]of byte (16 байт требовалось на описатель блока памяти))


 
Tano   (2002-11-19 21:01) [16]


> han_malign © (19.11.02 10:46)

Великолепно! Это окончательно все проясняет. Насчет предела памяти я знал, поэтому и константу верхнего предела так считал (только моя запись 128 байт, но это не важно), но, похоже, это вышло коряво. Ваш пример позволит даже не думать об этом (при выделении памяти я сам проверяю диапазоны и возможность выделения памяти). Спасибо!

Термин Самоадресуемая запись я не придумал, а прочитал в довольно умной и толстой книге Архангельского "Программирование в Delphi 6" БИНОМ 2002 (п.15.16.1, последний абзац - если не верите :-). Спасибо что помогли внести ясность.
С динамическими списками я хорошо знаком, но нигде не встречал такого их названия.

Благодарю всех за помошь!


 
Anatoly Podgoretsky   (2002-11-19 21:20) [17]

Только твоя запись, без учета на выравниваение, как минимум 131 байт и дико писать так, надо как минимум cMaxFieldsCount = (MaxInt div SizeOf(YourType)); при этом еще и резервировать минимум 16 байт для менеджера памяти, но и этого не достаточно, тебе выделено 2гб не для массива, а на все - на масиив на программу, на стек, на системные структуры и многое другое.
Ты же под один только массив запросил на 50 мб больше чем вообще доступно всего памяти.


 
Tano   (2002-11-20 03:51) [18]

Сдаюсь, сдаюсь, не нужно было ставить такую цифру!
Но Вы, Господин Anatoly Podgoretsky уж очень придирчивы (либо прочитали не все сообщения). Я уже написал, что:

1) Моя запись длиной 128 байт - ровнее некуда:
packed record //чтобы Delphi с перепугу поля не ровнял
Tp :TNodeType; //TNodeType = Byte; {1 байт}
Offs :Integer; {4 байта}
HD :THD; //THD = Integer; {4 байта}
Name :String[118]; {1+118 байт}
ИТОГО = 1 + 4 + 4 + (1+118) = 128

2) Выделение памяти контролирую сам.

Я для управления этой областью памяти вообще специально класс написал, где проверка на проверке, не говоря уже о счетчике элементов. А вопрос о указателе на массив записей возник из желания получать доступ к полям не через методы класса, а напрямую, побыстрее. Накладываю безразмерный массив на область памяти, проверяю допустимость индекса и читаю/пишу поле.
Даже в нашу эпоху гигагерцовых процов для определенных задач приходится считать и байты и такты. Для меня возможность сэкономить на вызове пары подпрограмм - уже значительный плюс. Не хочется попадать в ситуацию, когда на выцарапывание данных из памяти тратится больше времени, чем на их обработку.

В конце концов я использовал подсказку насчет array[0..0] (см. > han_malign © (19.11.02 10:46) ).
Нижним мозгом чувствовал, что есть простое решение, но не хватило опыта :-).


 
Tano   (2002-11-20 04:42) [19]

Кстати о 2Gb. Я вдруг вспомнил, что 32 разряда позволяют адресовать 4Gb памяти и внаглую потребовал выделить себе памяти 3Gb, 2.5Gb, 2Gb - не дают! Говорять, бери 1.3Gb и не пудри ядру мозги :-) /подкачка - 3.1Gb/. Пробовал командами LocalAlloc, VirtualAlloc.
Но это уже другая история...


 
MBo   (2002-11-20 06:01) [20]

>32 разряда позволяют адресовать 4Gb памяти
пользователю доступно 2 гига, остальным распоряжается система


 
KSergey   (2002-11-20 06:24) [21]

простите, уточню: каждому процессу выделено 2Гб на все про все. Остальные 2 забраны системой, как верно сказал МBo.
Хотя у вас есть выход: если не ошибаюсь, в Win2k "старших" версий (типа Advdnce Server или что-то такое. проверять в книжке лень) процессу выделяется существенно больше - что-то вроде 64Гб (возможно, половину так же требует система - не вникал), да и не уверен, что это при плоской модели памяти.
Вот только на кой такие массивы бешенные?! Может как-то иначе к задаче подойти?


 
Tano   (2002-11-20 09:00) [22]

Мне не нужен большой размер!!!
Рассуждения пошли не в ту сторону.
Дело в том, что обсуждение 2Gb развернулось вокруг предельной верхней границы массива записей. Я просто хотел в качестве верхней границы выбрать заведомо достаточное мне (большое) число. Мне за глаза хватит 12800 байт на ЭТОТ массив - он у меня соответствует числу полей таблицы (100 полей - это уже бред!).
Я не собираюсь замахиваться на гигабайты виртуальной памяти. Просто у меня подобных структур больше десятка, обращаться приходилось таким методом (использую запись, указанную в subj):

type
PTFieldID = ^TFieldID; //указатель на запись
var
BasePtr :Pointer; //указатель на массив структур. память выделяется LocalAlloc
...
begin
...
ElementPtr:=BasePtr+ElementIndex*SizeOf(TFieldID);
//доступ к полю:
PTFieldID(ElementPtr)^.название_поля

теперь, когда все выяснил, могу писать:

//доступ к полю:
PTFieldsID(BasePtr)^[ElementIndex].название_поля

разница в одну строку, но так как подобные обращения очень частые, то гораздо эффективнее выглядит второй вариант, где сам Delphi генерирует оптимальный код для вычисления адреса.
На полном серьезе - так программа работает быстрее на 60%!



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

Форум: "Основная";
Текущий архив: 2002.12.02;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.007 c
14-4575
copyr25
2002-11-06 18:41
2002.12.02
---|Ветка была без названия|---


3-4246
KonstVD
2002-11-14 13:28
2002.12.02
РАЗБИТЬ БОЛЬШУЮ ТАБЛИЦУ НА МЕНЬШИЕ


14-4577
Sergo
2002-11-11 13:36
2002.12.02
Kylix


1-4384
Niko
2002-11-20 18:18
2002.12.02
SynEdit


1-4473
andrek
2002-11-20 15:12
2002.12.02
Встроенный ASSEMBLER





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский