2014 dxdy logo

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

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




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


01/06/11
19
Все здравствуйте!

Такой вопрос по теме. В некоторой литературе пишут, что при передаче в функцию некоторых параметров как 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 
Заслуженный участник


27/07/12
1405
САФУ Архангельск
спросите на англиском freepascal форуме. а экономия за счет алгоритмы на много сильнее, чем за счет типа данных...

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


01/06/11
19
Sergey K в сообщении #674010 писал(а):
экономия за счет алгоритмы на много сильнее, чем за счет типа данных...

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

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


27/02/12
3895
Если описать массив в перечне параметров процедуры или функции,
поставив перед именем var, то при вызове не делается копия, а передается ссылка на исходный массив.
Если не ошибаюсь.

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


31/10/08
1244
monochromer
Цитата:
Однако следующий код демонстрирует, как мне кажется, обратное:

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

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

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

 Профиль  
                  
 
 Re: Передача const-параметров в функцию (Delphi/Pascal)
Сообщение20.01.2013, 12:48 
Заслуженный участник


11/05/08
32166
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 
Заморожен


14/09/10
72
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 
Аватара пользователя


01/06/11
19
Благодарю за помощь!

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


14/09/10
72
[Очень невнятно написал предыдущее сообщение. Постараюсь чуть точнее, и со ссылками.]

В 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 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



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

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


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group