Форум: "Начинающим";
Текущий архив: 2006.07.02;
Скачать: [xml.tar.bz2];
ВнизУказатели пойнтеры Найти похожие ветки
← →
Антибайт (2006-06-09 19:56) [0]Приветствую.
Голову сломал над сабжем. Подскажите, чем отличается ^ от @ и от Pointer (). Почему в исходниках вижу ^a и a^. В чём разница?
В свойствах проекта есть опция
Typed @ operator. Controls the type of pointer returned by the @ operator. Corresponds to {$T}.
Что она даёт?
Я так понимаю, что указатель содержит адрес, по которому размещены данные. Но как указывается размер этих данных? Т.е.
p : pointer
ничего не говорит о размере данных.
Например, у меня есть
а := 1;
А меня просят передать указатель на эту переменную. Мне надо передавать
p := @a; ?
А если я знаю адрес
p := $22;
а меня просят передать значение переменной. Мне надо делать так
a := p^; ?
А как быть, если у меня следующая структура
type
ta = record
a : integer;
p : pointer;
....
end;
var
a : ta;
А мне надо передать указатель на a.a и взять значение a.p? Так:
p := @a.a;
b := a.p^; ?
И вообще, в чём торч от указателей? Я могу, например, указатель передать из dll? Т.е. где-то в недрах dll сохранил string, но так как просто так string мне из dll не передать, я могу передать указатель на этот string?
К вражеским источникам просьба не отсылать, я не шпрехен зе дойч.
Справка борланд ситуацию не прояснила.
Книгу для начинающих прочитал - вопрос описан поверхностно. Хотелось бы услышать мнение профи.
← →
Desdechado © (2006-06-09 21:01) [1]Указатель - это переменная, хранящая адрес чего-то в памяти.
Бывают типизированные и безликие (Pointer).
Разницы на низком уровне между ними нет, но паскаль - язык строгих типов, поэтому появились типизированные указатели для уменьшения числа ошибок. Но их можно приводить один к другому явно, но ответственность тогда на программисте.
Есть еще операция взятия ссылки, т.е. получения адреса на что-то.
А также есть обращение по указателю, т.е. доступ к памяти, на которую указывает указатель.
И похожая операция разадресации ссылки.
Ссылка от указателя отличается мало, в основном местом использования.
← →
Rial © (2006-06-09 21:08) [2]Подскажите, чем отличается ^ от @ и от Pointer ().
@ - указатель на что - либо (переменную, функцию, и т.п.)
Т.е.
Type PInteger=^Integer;
Var PI:PInteger;
I:Integer;
begin
PI:=@I;
I:=10;
Теперь PI^=10.
^Type - тип, являющийся укзазателем на тип Type.
Var^ - данные, хранящиеся по указанному адресу.
Pointer() - преобразование "влоб", т.е.
I:Integer;
P:Pointer;
P:=Pointer(I) - не указатель на I, а указатель да область данных со смещением I.
Typed @ operator.
Опция определяет, будет ли компилятор ругаться на небезопасное испльзование указателей. Т.е. приведение указателей различных типов.
Но как указывается размер этих данных?
Никак. Все заботы ложатся на совесть програмиста.
Вот в AllocMem, например, этот размер записывается в предшестующие 4 байта.
p := $22;
а меня просят передать значение переменной. Мне надо делать так
a := p^; ?
Вот это к добру не приведет.
А мне надо передать указатель на a.a и взять значение a.p? Так:
p := @a.a;
b := a.p^; ?
b := a.p^ - не верно. В типе и речи не было об указателях.
Откуда домик то взялся ?
Просто b:=a.p;
И вообще, в чём торч от указателей?
Самый сложный вопрос :((
Type
ptMyRec=^TMyRec;
TMyRec=packed record
NExt,Prev:ptMyRec;
Data:Pointer;
end;
Торч от указателей в данном случае в том, чтобы ускорить работу программы
со списком данных, если не известно заранее количество элементов, а
также необходимо быстро осуществлять удаление и бодавление данных.
Ведь что бы добавть элемент в середину массива, придется двигать все
элементы справа на одну позицию, а тут - только кинуть указатель
на следующий и предыдущий элементы.
← →
parovoZZ © (2006-06-09 23:28) [3]
> Type PInteger=^Integer;
Это тот же Pointer, только типизированный. Так?
> p := $22;а меня просят передать значение переменной. Мне
> надо делать такa := p^; ?Вот это к добру не приведет.А мне
> надо передать указатель на a.a и взять значение a.p? Так:
> p := @a.a;b := a.p^; ?b := a.p^ - не верно. В типе и речи
> не было об указателях.Откуда домик то взялся ?Просто b:=a.
> p;type
ta = record
a : integer;
p : pointer;
....
end;
var
a : ta;
А как же быть?
← →
Rial © (2006-06-10 00:32) [4]
>
> Это тот же Pointer, только типизированный. Так?
>
Да.
Просто вот так сделать компилятор не даст:
Var P:Pointer;
I:Integer;
begin
P:=@I;
If (P^=$100)then begin
...
end;
end;
Это все из -за строгого контроля типов. Возможна разадресация только
типизированного указателя (если тип данных опеределен), Т.о. компилятор
уверен, что программист делает именно то, что и хотел.
> А как же быть?
Я же говорю:
p := @a.a;
b:=a.p;
← →
Антибайт (2006-06-10 01:21) [5]Так ведь у меня b : integer;, а a.p : pointer;
> p := $22;а меня просят передать значение переменной. Мне
> надо делать такa := p^; ?Вот это к добру не приведет.
А в чём криминал?
#######
Есть следующее:type
PTableData = ^TTableData;
TTableData = record
ID : word;
Table : TTables;
end;
Далее, в процедуре
procedure Unknown;
var
TableData : TTableData;
TableData_ : PTableData;
begin //TrV : TTreeView;
New (TableData_);
TableData_^.ID := 0;
TableData_^.Table := Journal;
MainNode := TrV.Items.AddObject (Node, User, TableData_);//Сохранили информацию.
//Далее считываем
//А вот здесь я намудрил. Не догоняю, как проще. Хотя работает.
TableData.ID := PTableData (Node.Data)^.ID;
TableData.Table := PTableData (Node.Data)^.Table;
end;
А как теперь этот указатель удалить? Dispose (Node.Data) не даёт уверенности.
← →
Rial © (2006-06-10 01:43) [6]
> Так ведь у меня b : integer;
Первый раз слышу. Раньше надо было говорить.
> > p := $22;а меня просят передать значение переменной. Мне
> > надо делать такa := p^; ?Вот это к добру не приведет.
>
> А в чём криминал?
Прсто маловероятно, что по этому адресу что-либо находится.
Рисуешь схлопотать AV. Да и в общем случае угадать число
с адресом сложно.
Как минимум, нужно складывать, например
rec=packed record
a,b:integer;
end;
rec.a:=10;
PInteger(@Rec.A+4)^:=18;
TableData.ID := PTableData (Node.Data)^.ID;
TableData.Table := PTableData (Node.Data)^.Table;
А смысл в копировании ?
Все же уже есть в TableData_.
На крайняк можно TableData:=TableData_^;
> А как теперь этот указатель удалить? Dispose (Node.Data)
> не даёт уверенности.
Зря. New делает ни что иное, как выделение памяти под SizeOf(Структура),
Dispose тоже учитывает размер структуры. Так что сомнения - прочь.
← →
Антибайт (2006-06-10 03:38) [7]
> Прсто маловероятно, что по этому адресу что-либо находится.
А в общем случае? Естественно, что я подразумеваю о нормальном стечении обстоятельств.
А вот С TTReeView не понятно. Как выудить инфу из Node.Data? TableData := Node.Data^ не работает. Может нужен packed record?
← →
Zeqfreed © (2006-06-10 04:28) [8]
> TableData := Node.Data^ не работает.
Очень даже работает, только надо не забывать приводить к нужному типу.
← →
Антибайт (2006-06-10 07:29) [9]Вот так
TableData := PTableData (Node.Data)^; ?
← →
begin...end © (2006-06-10 09:26) [10]> Rial © (10.06.06 01:43) [6]
> Рисуешь схлопотать AV.
Даже не рискует, а гарантированно получит. Потому что адреса со столь малыми адресами (например, в Win2000 -- с 0 по $FFFF) принадлежат разделу для выявления нулевых указателей, и любое обращение к памяти по этим адресам вызовет ошибку доступа.
> New делает ни что иное, как выделение памяти под SizeOf(Структура),
> Dispose тоже учитывает размер структуры. Так что сомнения
> - прочь.
Во-первых, New не только выделяет память, но и инициализирует поля типа длинных строк или динамических массивов, если таковые имеются в структуре, для которой эта память выделяется. А во-вторых, при вызове Dispose следует явно указывать тип указателя: Dispose(PTableData(Node.Data)), иначе такие поля не будут автоматически финализированы, и получится утечка памяти.
← →
tesseract © (2006-06-10 10:59) [11]
> А во-вторых, при вызове Dispose следует явно указывать
> тип указателя:
Не факт, Dipsose и создан(в отличие) для того что-бы сначала финализировать динамические данные. В отличие от freemem. Delphi хранит размер указателя в отдельном месте.
← →
begin...end © (2006-06-10 11:26) [12]> tesseract © (10.06.06 10:59) [11]
> Не факт
Другими словами, Вы утверждаете, что в случае наличия в структуре таких полей при вызове Dispose тип указателя можно не указывать явно.
ОК, голословное утверждение у Вас уже есть. Теперь дело за малым -- привести РЕАЛЬНЫЙ КОД, его подтверждающий. То есть показывающий, что никакой утечки памяти не будет.
А я пока приведу код, подтверждающий МОЮ точку зрения:type
PRec = ^TRec;
TRec = record
A: array of Integer
end;
var
TypedPointer: PRec;
UntypedPointer: Pointer;
I: Integer;
begin
I := AllocMemSize;
New(TypedPointer);
SetLength(TypedPointer.A, 100);
UntypedPointer := TypedPointer;
Dispose(UntypedPointer);
ShowMessageFmt("Утечка: %d байт", [AllocMemSize - I])
end
← →
tesseract © (2006-06-10 11:55) [13]
> UntypedPointer := TypedPointer;
> Dispose(UntypedPointer);
При использовании нетипизированных указателей, полностью подтверждаю ошибочность [11] .
Я имел в виду использование типизированных.
← →
begin...end © (2006-06-10 12:01) [14]> tesseract © (10.06.06 11:55) [13]
> Я имел в виду использование типизированных.
А речь шла об освобождении памяти, связанной с Node.Data, то есть с НЕтипизированным указателем. Поэтому [11] -- оно немного "не в кассу", не находите?
← →
tesseract © (2006-06-10 12:07) [15]
> Поэтому [11] -- оно немного "не в кассу", не находите?
Да признался уже, просто я обычно создавал отдельный массив под типизированные указатели.
← →
Антибайт (2006-06-11 01:02) [16]Ну ладно, спасибо, хоть прояснили ситуацию.
← →
parovoZZ © (2006-06-11 01:27) [17]Резюмируя всё сказанное, надо делать так
TableData := PTableData (Node.Data)^;
иDispose (PTableData (Node.Data));
← →
Ihor Osov'yak © (2006-06-11 13:50) [18]немного офтопа..
в свое время, когда разбирался со всем этим, анализировал код, что генерировал компилятор... По Ctrl_Alt_C на брекпоинте..
Но в общем то в мире персоналок я начал программировать на ассемблере, так что не знаю, приемлим ли этот способ в общем случае, но мне это очень помогало..
← →
parovoZZ © (2006-06-11 18:23) [19]А у меня с асмом туго...
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.07.02;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.009 c