адрес переменной указателя, а не его значение

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

адрес переменной указателя, а не его значение

Сообщение mik1133 » 27.08.2010 14:00:39

Народ, подскажите!
При передаче в функцию переменной типа указатель в функцию передается адрес этой переменной, а не ее значение!? Почему и можно ли это как-то изменить? Дело в том что в программах на языке с в функцию передается именно значение переменной-указателя, а не ее адрес.

Есть код:
Код: Выделить всё
type
  PNewStruct = ^TNewStruct;
  TNewStruct = record
     a: LongInt;
  end;

var
  st: TNewStruct;
  pst: ^TnewStruct;

function F1(pst: PNewStruct): LongInt; cdecl;
var
  i: LongInt;
begin
  i := pst^.a + 1;
  Result := i;
end;

begin
  pst := @st;
  F1(pst);
end.


Ассемблерный листинг:
F1(pst)
0804EF08 pushl 0x80d3df0
0804EF0E call 0x804ee90 <F1>

где, 0x80d3df0 — адрес на переменную pst. По этому адресу хранится значение 0x080D3DEC. А это адрес на переменную st. По этому адресу хранится значение 00000000. Так вот, по идее должен передаваться в функцию именно адрес переменной st, т.е. - 0x080D3DEC.

Интересно, что в Delphi работает так же как и в программах на языке с. Т. е. передается адрес переменной st.



Пишу на Linux, использую паскаль версии: Free Pascal Compiler version 2.4.0-2 [2010/03/06] for i386
IDE — MSEgui version: 2.2
MSEide version: 2.2

Что с опцией -Mdelphi, что с -Mobjfpc результат одинаков.
Последний раз редактировалось mik1133 27.08.2010 16:54:04, всего редактировалось 3 раз(а).
mik1133
незнакомец
 
Сообщения: 2
Зарегистрирован: 27.08.2010 13:22:25

Re: адрес переменной указателя, а не его значение? почему?

Сообщение Maxizar » 27.08.2010 15:01:18

Код: Выделить всё
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

type
  PNewStruct = ^TNewStruct;
  TNewStruct = record
     a: LongInt;
  end;

var
  Form1: TForm1;
  PSt:PNewStruct;
  St:TNewStruct;
implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
Procedure Proc1(P:PNewStruct); //Передаем указатель типа PNewStruct который должен указывать
begin                          //на переменную типа TNewStruct
Caption:=IntToStr(P^.a);
end;

Procedure Proc2(var S:TNewStruct); //Передаем указатель на переменную типа TNewStruct
begin
Caption:=IntToStr(S.a);
end;

Procedure Proc3(Const S:TNewStruct);//Передаем ссылку на S
begin
Caption:=IntToStr(S.a);
end;

Procedure Proc4(S:TNewStruct);//Передаем копию S
begin
Caption:=IntToStr(S.a);
end;

begin
St.a:=10; //Инициализация переменной St
PSt:=@St; //Теперь PSt указывает на St
//Пример вызова процедур
Proc1(Pst);
//Proc2(St);
//Proc3(St);
//Proc4(St);

//Любой из этих вызовов должен вывести в Caption надпись 10...
end;

end.

Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14

Re: адрес переменной указателя, а не его значение? почему?

Сообщение mik1133 » 27.08.2010 15:53:11

В том что этот код будет прекрасно работать - никаких сомнений нет. И все потому, что объявленные функции Proc1, Proc2, Proc3, Proc4 вызываются тут же в паскалевском модуле.

Но все дело в том, что, например, в Linux многочисленные модули (с расширением .so) написаны не на Pascal а на c, c++. И в этих модулях есть различные функции, с параметрами типа указатели. И если в паскалевскую программу подключить такой .so модуль, затем получить адрес какой-нибудь функции из этого модуля и попытаться в эту функцию, написанную на с, передать параметр типа указатель, то получается жо...а.
Потому что, как я объяснял, и в программах написанных на с, c++ и в программах написанных на Delphi при передаче в функцию переменной-указателя в функцию будет передано значение, которое хранит эта переменная, а во FreePascal, почему-то, передается адрес этой пременной, а не ее значение (см. ассемблерный листинг).

Код: Выделить всё

tstruct st;
tstruct* pst;

int testfunc(tstruct* pst)
{
   int i;

   i = pst->a + 1;
   return i;
}

int main()
{
   pst = &st;
   testfunc(pst);
}

перед вызовом testfunc в стек поместиться 0х08175120 - где 0х08175120 - адрес на переменную st

Код: Выделить всё
type
  PNewStruct = ^TNewStruct;
  TNewStruct = record
     a: LongInt;
  end;

var
  st: TNewStruct;
  pst: ^TnewStruct;

function F1(pst: PNewStruct): LongInt; cdecl;
var
  i: LongInt;
begin
  i := pst^.a + 1;
  Result := i;
end;

begin
  pst := @st;
  F1(pst);
end.

перед вызовом F1 в стек поместиться 0х080FE604 - где 0х080FE604 - адрес на переменную pst

В результате внутри функции из модуля полученное значение будет рассматриваться как адрес на какой-либо объект, а на самом деле FreePascal передал адрес на свою переменную а не на объект, который ожидает функция.

Из-за этой особенности (бага? фичи?) получается что FreePascal не совместим ни с кими другими модулями написанными на других языках.
mik1133
незнакомец
 
Сообщения: 2
Зарегистрирован: 27.08.2010 13:22:25

Re: адрес переменной указателя, а не его значение

Сообщение Mr.Smart » 27.08.2010 17:09:21

Что-то вы не правильно понимаете. Всё прекрасно работает в связки с Си.
Приведите объявление вашей функции на Си.
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: адрес переменной указателя, а не его значение

Сообщение B4rr4cuda » 28.08.2010 03:41:24

Случайно не с этим ли связаны проблемы с работой библиотеки vlc при вызовах из FPC, с которыми столкнулся NXP?
http://freepascal.ru/forum/viewtopic.php?f=9&t=6098&p=44991
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Re: адрес переменной указателя, а не его значение

Сообщение petrovv » 28.08.2010 19:34:13

а если передавать не указатель на структуру, а структуру, т.е.
Код: Выделить всё
function F1(pst: TNewStruct): LongInt; cdecl;
var
  i: LongInt;
begin
  i := pst.a + 1;
  Result := i;
end;

Может тогда компилятор передаст в функцию указатель на структуру, сам не проверял.
petrovv
незнакомец
 
Сообщения: 9
Зарегистрирован: 02.06.2010 23:58:02

Re: адрес переменной указателя, а не его значение

Сообщение Max Rusov » 28.08.2010 20:28:10

Что то вы путаете.

Код: Выделить всё
  pst := @st;
      mov   eax,offset U_P$PROGRAM_ST
      mov   dword ptr [U_P$PROGRAM_PST],eax
  F1(pst);
      push   dword ptr [U_P$PROGRAM_PST]
      call   P$PROGRAM_F1$PNEWSTRUCT$$LONGINT
      pop   ebx


Не вижу проблем
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: адрес переменной указателя, а не его значение

Сообщение Vadim » 29.08.2010 19:37:51

mik1133 писал(а):и в программах написанных на с, c++ и в программах написанных на Delphi при передаче в функцию переменной-указателя в функцию будет передано значение, которое хранит эта переменная

А вот это неправда. :)
mik1133 писал(а):pst->a

В этом коде мы видим не обращение непосредственно к указателю, а взятие значения по указанному адресу.
В Си это сделано логично, т.к. используется специальный символ, вместо точки - стрелочка. Т.е. мы видим по коду, что работаем с указателем. В Дельфи довели работу с указателями до абсурда - там по коду невозможно определить, не заглядывая в объявления, работаете ли вы с указателем или статической переменной. Поэтому на Дельфи кивать не надо, Дельфи - отстой, там всё запутано. Во FreePascal всё распутали и стало всё понятно. :)
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: адрес переменной указателя, а не его значение

Сообщение mike » 30.08.2010 19:06:27

Vadim писал(а):В Дельфи довели работу с указателями до абсурда - там по коду невозможно определить, не заглядывая в объявления, работаете ли вы с указателем или статической переменной

В делфях только упростили синтаксис для лаконичности обращения к динамическим экземплярам классов (которые статическими не бывают, а значит сишный маразм со специальным разделителем просто не нужен). Вариант pst^.a для указателей на структуры и объекты старой модели никто не отменял, он прекрасно работает и используется нормальными разработчиками. А тот факт, что допустимо опускать оператор разыменования и писать pst.a еще не значит, что так делать нужно.
mike
новенький
 
Сообщения: 40
Зарегистрирован: 23.02.2007 17:25:00

Re: адрес переменной указателя, а не его значение

Сообщение Vadim » 31.08.2010 02:27:01

mike писал(а):А тот факт, что допустимо опускать оператор разыменования и писать pst.a еще не значит, что так делать нужно.

Так вот и я про то же. ;) И на основе этого в мозгах молодых и неопытных программистов происходит страшная путаница. Это я и называю абсурдом, а вовсе не работу с классами.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16

Рейтинг@Mail.ru