Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.011 c
2-1150178919
Хой
2006-06-13 10:08
2006.07.02
Оператор inherited


2-1150377106
Scavenger
2006-06-15 17:11
2006.07.02
Задержка времени


1-1148157851
learner
2006-05-21 00:44
2006.07.02
Сохранение коллекции в потоке.


2-1150039565
learner
2006-06-11 19:26
2006.07.02
Правильное ведение лога с использованием нитей


11-1129729491
Dmitry Galin
2005-10-19 17:44
2006.07.02
KOL & BDS 2005?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский