Форум: "Основная";
Текущий архив: 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.044 c