2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Передача const-параметров в функцию (Delphi/Pascal)
Сообщение20.01.2013, 06:57 
Аватара пользователя
Все здравствуйте!

Такой вопрос по теме. В некоторой литературе пишут, что при передаче в функцию некоторых параметров как const они не копируются в локальную память, что позволяет экономить память и увеличить скорость работы в случае "больших" данных.

Например, цитата из книги Фаронова "Delphi. Программирование на языке высокого уровня":
"В случае параметра-константы в подпрограмму также передается адрес области памяти, в которой располагается переменная или вычисленное значение. Однако компилятор блокирует любые присваивания параметру-константе нового значения в теле подпрограммы."

Однако следующий код демонстрирует, как мне кажется, обратное:

Используется синтаксис Delphi
program Test;

procedure prob(const c:byte);
begin
  writeln(longint(addr(c)));
end;

var a: byte;

begin
  a:=0;
  writeln(longint(addr(a)));
  prob(a);  
end.


Вывод программы (Тесты проводил в средах Delphi 7, Delphi XE3, Lazarus 1.0.4.):
4237208
1245040

Значит, все-таки const-параметры копируются в локальную память?

 
 
 
 Re: Передача const-параметров в функцию (Delphi/Pascal)
Сообщение20.01.2013, 08:44 
спросите на англиском freepascal форуме. а экономия за счет алгоритмы на много сильнее, чем за счет типа данных...

 
 
 
 Re: Передача const-параметров в функцию (Delphi/Pascal)
Сообщение20.01.2013, 09:03 
Аватара пользователя
Sergey K в сообщении #674010 писал(а):
экономия за счет алгоритмы на много сильнее, чем за счет типа данных...

У меня, к примеру, есть итерационный процесс, где на каждом шаге формируется матрица порядка 1000. Затем она передается в процедуру решения СЛАУ. Представляете, какие затраты, если на каждом шаге в локальную память будет копироваться двумерный массив 1000x1000.

 
 
 
 Re: Передача const-параметров в функцию (Delphi/Pascal)
Сообщение20.01.2013, 09:41 
Аватара пользователя
Если описать массив в перечне параметров процедуры или функции,
поставив перед именем var, то при вызове не делается копия, а передается ссылка на исходный массив.
Если не ошибаюсь.

 
 
 
 Re: Передача const-параметров в функцию (Delphi/Pascal)
Сообщение20.01.2013, 09:45 
Аватара пользователя
monochromer
Цитата:
Однако следующий код демонстрирует, как мне кажется, обратное:

Эффект наблюдателя.
Вы в процедуре запрашиваете addr а какой addr у константы? Правильно ни какой, но для вас компилятор его и создаёт. Уберите Addr и сравните дизассемблированный код с и без.
А во-вторых вы же сами пишите что это не всегда бывает. Просто регистров мало констант, переменных много разумеется компилятор сохранит их в стек если ему будет не хватать регистров.

Цитата:
У меня, к примеру, есть итерационный процесс, где на каждом шаге формируется матрица порядка 1000. Затем она передается в процедуру решения СЛАУ. Представляете, какие затраты, если на каждом шаге в локальную память будет копироваться двумерный массив 1000x1000.

Не будет она просто в стек не влезет. Поэтому давно отказались от такого. Массивы теперь как правило выделяются в куче. И копирование массива не происходит. В место этого просто создается ещё одна ссылка которая также указывает на этот массив.

 
 
 
 Re: Передача const-параметров в функцию (Delphi/Pascal)
Сообщение20.01.2013, 12:48 
monochromer в сообщении #673993 писал(а):
"В случае параметра-константы в подпрограмму также передается адрес области памяти, в которой располагается переменная или вычисленное значение.

Это зависит от компилятора. Пример:

Код:
type  t = array[1..40000] of byte;
var  a: t;
     x: integer;

procedure c(d: t; var e: integer);
begin
  e:=d[1];
end;

begin

  c(a, x);

end.

7-й Турбо Паскаль при попытке запуска реагирует вполне ожидаемо:

Error 202: Stack overflow error.

С другой стороны, я смутно припоминаю, что вроде бы иногда бывает наоборот: при вызове переменных по ссылке они иногда заносятся в стек фактически своими значениями (если они короткие). Но, может, что-то и путаю.

 
 
 
 Re: Передача const-параметров в функцию (Delphi/Pascal)
Сообщение20.01.2013, 15:49 
monochromer, это зависит от компилятора. А для конкретного компилятора от типа данных и настроек компилятора.

В Delphi 5 при включенной оптимизации кода, в вашем примере переменная a заносится в регистр eax, и уже в самой функции копируется из регистра в стек. Адрес копии в стеке и наблюдается вторым длинным целым при выполнении программы.

А вот в следующей модификации передачи по значению не происходит. Вместо этого передаются указатель на переменную a. Но механизм передачи тот же: адрес массива копируется в регистр eax, а затем в функции заносится в стек.

код: [ скачать ] [ спрятать ]
Используется синтаксис Delphi
program cparam;

type t = array[1..10000] of extended;

procedure prob(const x: t);
begin
 writeln(LongWord(addr(x)));
end;

var
 a: t;
begin
 a[1]:= 1;
 writeln(longword(addr(a)));
 prob(a);
end.

В ранних версиях компиляторов массивы передавались по ссылке, даже если в функции были описаны как передаваемые по значению (Си, Паскаль; например, TP5). В более поздних версиях в описании параметра было добавлено ключевое слово const, и при таком описании уже компилятор принимает решение о способе физической передачи аргумента. Компилятор лишь гарантирует, что аргумент, который описан как const параметр, не может модифицироваться в теле процедуры. Естественно, массивы, как правило, передаются по ссылке. Если параметр описан как передаваемый по значению, то фактический параметр обязательно копируется (в стек или регистр), если он модифицируется в теле процедуры.

Так что в книге, в принципе, все написано правильно.

Upd. Добавил: "если он модифицируется в теле процедуры".

 
 
 
 Re: Передача const-параметров в функцию (Delphi/Pascal)
Сообщение20.01.2013, 18:31 
Аватара пользователя
Благодарю за помощь!

 
 
 
 Re: Передача const-параметров в функцию (Delphi/Pascal)
Сообщение26.01.2013, 15:59 
[Очень невнятно написал предыдущее сообщение. Постараюсь чуть точнее, и со ссылками.]

В Delphi 5 [1] параметры-переменные [var parameters] всегда передаются по ссылке, как 32-битные указатели.

Параметры-значения [value parameters] или параметры-постоянные [const parameters] передаются по значению (by value) или по ссылке (by reference), в зависимости от типа и размера: ... множество, запись или статический массив длиной 1, 2 или 4 байта передаются как 8-ми, 16-ти и 32-ух битные значения. Более длинные множества, записи или статические массивы передаются как 32-битный указатель на значение. Исключением из этого правила являются передача записей под соглашениями cdecl, stdcall, sefecall. …

Под соглашениями pascal, ... параметры передаются через стек. Под соглашением register до трех параметров передаётся через регистры процессора, а остальные через стек. Первые три параметра передаются через регистры EAX, EDX, ECX. Вещественные параметры и указатели на методы не квалифицируются как регистровые параметры.

(подробнее изложено в фирменной документации).


В Turbo Pascal 5, 6, 7 [с учетом, когда был введено ключевое слово const в описании параметра] правила те же, что и в Delphi под соглашением pascal. См., например [2].

Во Free Pascal нельзя предполагать, что длинный параметр-постоянная, например массив длиннее четырех байт, передается по ссылке [3]. [Сужу по документации, я им не пользовался].

Как выше написано, в Delphi 5 и TP 6, 7 длинный параметр-значение передается по ссылке. Выделение памяти для значений массива происходит в самой процедуре. Поэтому ошибка переполнения стека возникает не при вызове процедуры, а на её «входе», т.е. при выделении памяти под локальные переменные. Даже в отладке на высоком уровне (не в окне CPU [Delphi], или во внешнем отладчике [в TP]) это хорошо видно.

[1] Object Pascal Language guide [Delphi 5]. Chapter 12 Program control / Parameters and function results / Parameter passing. (документацию легко нагуглит по фразе “Object Pascal Language guide”, например, pdf.)
[2] Руководство по языку Borland Pascal 7. Часть III. В среде Borland Pascal. Глава 22 Вопрос упраления. (html) [Нагуглить можно много ссылок].
[3] Reference guide for Free Pascal, version 2.6.0. Document version 2.6 (pdf). Using function and procedures / Constant parameters (p. 152, Remark).

 
 
 [ Сообщений: 9 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group