Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.02.11;
Скачать: CL | DM;

Вниз

Указатели   Найти похожие ветки 

 
compiller   (2007-01-12 18:59) [0]

Здравствуйте. У меня несколько вопросов по указателям:
1) При получении указателя на элемент массива извне все работает нормально, в примере 2, p содержит неправильное значение.

Пример 1:
P := @MyObject.Items[0]; // Возвращает реальный указатель

Пример 2:
function TMyObject.AddItem;
begin
SetLength(Items, Length(Items)+1);
Items[High(Items)] := TMyItem.Create;

P := @Items[0]; // Возвращает неправильное значение
end;

При вызове функции значение p иногда изменяется, а иногда нет! Я не могу понять из за чего это происходит. Может баг в delphi, или это у меня руки кривые?

2) Почему, если использовать прототип 1, то значение в eax больше реального на 4?

// Прототип функции
1) function PtrAdd(const P; X: Integer): Pointer;
2) function PtrAdd(P: Pointer; X: Integer): Pointer;

// Код функции
asm
mov  eax,P
mov  edx,[X]
add  eax,edx
mov  Result,eax
end;


 
DevilDevil ©   (2007-01-13 16:45) [1]

1) Указатель в обоих случаях верен. Другое дело, что при изменении размерности динамического массива происходит перераспределение занимаемоё памяти, вследствие чего весь динамичесикий массив может "оказаться" в другой области памяти, это не из-за Delphi, а из-за Винды, точнее из-за особенности оперативной памяти.

2) а) у тебя просто функция или функция класса? Это принципиально важно
   б) зачем тебе использовать ассемблер?
   в) если это просто функция, то: P === eax, X === edx, в качестве результирующего значения Result использовать не надо, результат оставь в eax:
  function PtrAdd(P: Pointer; X: Integer): Pointer;
  asm
     add eax, edx
  end;  

   г) в реальных условиях и проще и понятнее делать так:
P2 := pbyte(P1) + X;
   д) ну а если .... незнаю как написать, пистаь не буду ;)

P.S. незабудь сказать спасибо ;)


 
ors_archangel ©   (2007-01-13 17:44) [2]

2 compiler
1

> P := @Items[0]; // Возвращает неправильное значение

Кто возвращает?
Что значит неправильное значение?
  А что нужно?
Что такое P?
Это глобальная переменная?
 Зачем ты её меняешь в методе класса?
2

>  Почему … значение в eax больше реального на 4?

Потому что const - это передача по ссылке (в данном случае и чаще всего), т.е. передаётся не значение указателя, а ссылка на этот указатель, например указатель расположен в стеке по адресу [esp+offs] и указывает на что-то с адрессом $00aabbcc, тогда в 1) передаётся esp+offs, а во 2) передаётся $00aabbcc


 
ors_archangel ©   (2007-01-13 17:50) [3]


DevilDevil ©   (13.01.07 16:45) [1]
>  динамичесикий массив может "оказаться" в другой области
> памяти, это не из-за Delphi, а из-за Винды, точнее из-за
> особенности оперативной памяти.

Ещё точнее это из-за особенностей менеджера памяти каждой Delphi-программы

> в реальных условиях и проще и понятнее делать так:
> P2 := pbyte(P1) + X;

В нереальных, но существующих условиях делать это даст только operator, который not applicable to this operand type. Такие штуки могут прокатывать только с PChar:

 p2 := pchar(p1) + x;


 
DevilDevil ©   (2007-01-13 18:03) [4]


> В нереальных, но существующих условиях делать это даст только
> operator, который not applicable to this operand type. Такие
> штуки могут прокатывать только с PChar:
>
>  p2 := pchar(p1) + x;


Такие шутки прокатывают абсолютно со всеми указателями


 
ors_archangel ©   (2007-01-13 20:11) [5]


> Такие шутки прокатывают абсолютно со всеми указателями

Пример кода, в котором p1,p2: pointer, x: integer, и который будет хотя бы компилироваться, пожалуйста, если не сложно (компилироваться в Delphi7!). Извини, но ты не прав: не существует оператора "+", который мог бы оперировать с указательными типами: нельзя складывать укзатели, нельзя к указателю прибавить любой другой тип, для указателей существуют только оператор разымёнывания "^". Почему все пишут, допустим

 PDword(integer(p)+8)^,

а не "проще и понятнее":

 PDword(p+8)^.

Но это, как я сказал в [3], не относится к типу PChar, если расширенный синтаксис включен {$x+}, если выключён, то даже

 p2 := pchar(p) + x;

не будет не то что работать, но даже компилироваться, это и есть строгая типизация в понимании Паскаля. Попробуй, если не веришь


 
DevilDevil ©   (2007-01-13 20:29) [6]

Мда, действительно ошибся... но ошибся небеспочвенно:

1) Над указателями в Си действует оператор "+".
2) p1 увеличится на 10:
procedure TForm1.FormCreate(Sender: TObject);
var
 p1, p2 : pword;
begin
 p1 := @Self;
 Inc(p1, 5);
end;


 
ors_archangel ©   (2007-01-13 20:37) [7]


> DevilDevil ©   (13.01.07 20:29) [6]

Я сразу так и подумал, что ты Си вспомнил :)
Inc - кстати, хорошее решение, ну а с PChar, кстати, можно даже так писать

 p + 2;

- прибавит 2 (именно 2, потому что sizeof(char)=1) к p (если {$x+}), - единственый случай, когда операция "+" может не возвращать значения :)


 
compiller   (2007-01-21 23:40) [8]


> DevilDevil ©   (13.01.07 16:45) [1]


Функция не принадлежт классу.

С этим уже разобрался.


> ors_archangel ©   (13.01.07 17:44) [2]


P, глобальная переменная. Весь прикол в том, что если присваивать значение P из класса в котором содержится Items, то при обращении по адресу P, вылетает raise

Спасибо за помощь


 
Eraser ©   (2007-01-22 01:06) [9]

> [5] ors_archangel ©   (13.01.07 20:11)


> нельзя складывать укзатели

и это правильно ) просто в этом нет никакого смысла ))
в если уж очень нужно, то через приведение типов это легко делается.

> [0] compiller   (12.01.07 18:59)

что такое Items ?


 
tesseract ©   (2007-01-22 12:10) [10]


>> нельзя складывать укзатели
> и это правильно ) просто в этом нет никакого смысла ))


Иногда есть. Вроде так должно сработать

myaddr:=Cardinal(@MyPointer);

Что -то такое делал. Зачем не помню.


 
Ega23 ©   (2007-01-22 14:45) [11]


> Что -то такое делал. Зачем не помню.
>


Передача callback-адреса?


 
evvcom ©   (2007-01-22 15:15) [12]

> [2] ors_archangel ©   (13.01.07 17:44)
> Потому что const - это передача по ссылке (в данном случае
> и чаще всего), т.е. передаётся не значение указателя, а
> ссылка на этот указатель

Передается в любом случае 4 байтовое значение. В данном случае передается именно значение указателя. Вот с var-ом передался бы указатель на этот Pointer. Я смотрел как-то передачу array[0..N] of Byte (Char). Если N<=3, то передается массив "значением", т.е. одним 4-х байтовым значением, иначе указатель на 0-й символ.



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

Текущий архив: 2007.02.11;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.052 c
15-1169304400
vidiv
2007-01-20 17:46
2007.02.11
Не нравится


15-1169485507
Virgo_Style
2007-01-22 20:05
2007.02.11
День авиации ПВО


3-1163606293
AlexWlad
2006-11-15 18:58
2007.02.11
Невозврат значения из Stored Procedure


15-1169161784
hmmcensured
2007-01-19 02:09
2007.02.11
вопрос по SEO


4-1158081492
vidiv
2006-09-12 21:18
2007.02.11
Копирование выделенного текста с Активного окна.