Функции в качестве параметров процедур

Форум для изучающих FPC и их учителей.

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

Ответить
Ro_jA
незнакомец
Сообщения: 4
Зарегистрирован: 03.05.2013 20:59:59

Функции в качестве параметров процедур

Сообщение Ro_jA »

Товарищи,подскажите, это баг или фича?
Берем, скажем, процедуру с тремя параметрами. Эти параметры задаем с помощью трёх функций, работающих со строкой. Во время работы программы функции вызываются в нормальном порядке, а результаты в процедуру возвращаются в обратном. Вот пример:

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

var
        a:string;
        i:integer;

        function f1(b:string):integer;
        begin
                inc(i);
                writeln('f#',i);
                f1:=ord(b[1]);
                writeln(chr(f1));
                delete(a,1,1);
                writeln
        end;

        procedure p1(a,b,c:integer);
        begin
                writeln(chr(a));
                writeln(chr(b));
                writeln(chr(c))
        end;

begin
        i:=0;
        readln(a);
        p1(f1(a),f1(a),f1(a));
        readln
end.

Вводим строку 'abc'
На экране видим:
f#1
a

f#2
b

f#3
c
{то есть функции вызываются в правильном порядке, но потом:}

c
b
a
{то есть процедура берет их в обратном.}
Очень, знаете ли, обидная и труднообнаруживаемая проблема.
Компилятор 2.6.2.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

Фича.
Компилятор вычисляет аргументы в произвольном порядке, который может зависеть от типа вызываемой процедуры и целевой платформы.
Ro_jA
незнакомец
Сообщения: 4
Зарегистрирован: 03.05.2013 20:59:59

Сообщение Ro_jA »

И какая же практическая польза от этой фичи? Каким образом мне при последующем написании программ удостовериться, что все вычисляется в нужном порядке?
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

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

var
  t1,t2,t3: integer;
begin
  t1:=f1(a);
  t2:=f1(a);
  t3:=f1(a);
  p1(t1,t2,t3);
end;


Код, зависящий от порядка вычисления аргументов функции, писать не нужно.
Аватара пользователя
runewalsh
энтузиаст
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Сообщение runewalsh »

Записывать во временные переменные в нужном порядке. Фича оправданна и имеет место в абсолютном большинстве компилируемых языков, т. к. предоставляет компилятору простор для оптимизации. А вот вызывать зависящие друг от друга функции в пределах одной точки следования — опасно; даже в шарподжавах, где порядок определён, это как минимум моветон.

UPD: ну вот, меня опередили. ^^
Ro_jA
незнакомец
Сообщения: 4
Зарегистрирован: 03.05.2013 20:59:59

Сообщение Ro_jA »

Ну что ж, спасибо за советы. Непонятно, почему в документации ни слова на этот счет. В ref вообще ничего,а в prog я нашел строчку "If a function is called that returns a variable of type String, Set, Record, Object or
Array, then an address to store the function result in, is also passed to the procedure." которая,похоже вообще не о том.
Эмм, а как закрыть тему?
absdjfh
новенький
Сообщения: 60
Зарегистрирован: 21.01.2012 13:59:00

Сообщение absdjfh »

Ro_jA писал(а):Непонятно, почему в документации ни слова на этот счет.

Ну вот как нет, если есть? Глава 12, reference guide, expressions:
Remark: The order in which expressions of the same precedence are evaluated is not guaranteed to be left-to-right. In general, no assumptions on which expression is evaluated first should be made in such a case. The compiler will decide which expression to evaluate first based on optimization rules. Thus, in the following expression:

a := g(3) + f(2);
f(2) may be executed before g(3). This behaviour is distinctly different from Delphi or Turbo Pascal.

If one expression must be executed before the other, it is necessary to split up the statement using temporary results:

e1 := g(3);
a := e1 + f(2);
Ro_jA
незнакомец
Сообщения: 4
Зарегистрирован: 03.05.2013 20:59:59

Сообщение Ro_jA »

Как раз хотел задать вопрос насчет порядка вычислений в этом операторе. Я не нашел этого потому, что искал в процедурах и функциях, а до выражений руки не дошли. Могли бы и там упомянуть, на самом деле. В любом случае спасибо.
Mirage
энтузиаст
Сообщения: 880
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia
Контактная информация:

Сообщение Mirage »

Причем тут порядок вычисления выражений?
Порядок передачи параметров зависит от calling convention. Например, можно попробовать пометить функцию p1 как pascal.
Порядок вычисления параметров, конечно, может и отличаться от порядка их передачи, но на практике это врядли.
Конечно, закладываться на определенный порядок нельзя. Т.к. он неопределенный в общем случае.
absdjfh
новенький
Сообщения: 60
Зарегистрирован: 21.01.2012 13:59:00

Сообщение absdjfh »

Mirage писал(а):Т.к. он неопределенный в общем случае.

Он (порядок вычисления функций в выражениях и вызовах функций) неопределенный только в случае компилятора FPC. В TP (и, вероятно, delphi) можно было закладываться на такой порядок, и программа выводила (и выводит сейчас) ожидаемый (по человеческой логике) результат для любого варианта передачи параметров.
Самый правильный вариант, конечно, - не писать функций с побочными эффектами, особенно если без этого можно легко обойтись.
Ответить