Текущий архив: 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.48 MB
Время: 0.046 c