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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.04 c
15-1169200526
Prohodil Mimo
2007-01-19 12:55
2007.02.11
почему мигают лампочки на кулере?


15-1168986319
Tirael
2007-01-17 01:25
2007.02.11
нейросети


15-1169304400
vidiv
2007-01-20 17:46
2007.02.11
Не нравится


4-1159123295
wp2
2006-09-24 22:41
2007.02.11
NtCreateProcessEx какие параметры и их тип?


11-1147773413
AlexY
2006-05-16 13:56
2007.02.11
ActiveDirectory + KOLEdb.





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