Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2008.01.20;
Скачать: [xml.tar.bz2];

Вниз

Результат трехчасовых поисков ошибки в проекте :)   Найти похожие ветки 

 
Riply ©   (2007-12-10 17:08) [0]

Здравствуйте !
Допустим, у нас есть две ф-ии:

function Funct1(var Param: integer): integer;
begin
if Param = 0 then inc(Param, 1);
Result := Param;
end;

function Funct2(var Param: integer): integer;
begin
if Param = 0 then inc(Param, 2);
Result := Param;
end;


Что мы увидим в сообщении:

Param := 0;
ShowMessage(IntToStr(Funct1(Param) + Funct2(Param)));


Чур Delphi не пользоваться :)
Пол дня убила на поиск ошибки, зато новые знания :)


 
Palladin ©   (2007-12-10 17:10) [1]

3 и увидим


 
Rouse_ ©   (2007-12-10 17:10) [2]

1?


 
Alkid ©   (2007-12-10 17:11) [3]

Мда, а ещё кто-то за конструкции вида i = i++ + 1 С/C++ извращением считает...


 
Palladin ©   (2007-12-10 17:11) [4]

ой... 4 :)


 
Сергей М. ©   (2007-12-10 17:11) [5]


> Пол дня убила на поиск ошибки


Бедняга).. Целых пол-дня !!

Нет бы сразу пройтись отладчиком и выяснить, где таятся грабли)


 
Rouse_ ©   (2007-12-10 17:12) [6]

А, не, там еще сложение ж у тебя :)
Двойку увидим :)


 
Riply ©   (2007-12-10 17:13) [7]

Верных ответов, пока, нет :)


 
Palladin ©   (2007-12-10 17:14) [8]


> Rouse_ ©   (10.12.07 17:12) [6]

А var не заметил? :)

первая функция возвратит 1, изменит значение переменной на 1
вторая функция возвратит 3

1+3=4


 
Riply ©   (2007-12-10 17:14) [9]

> [6] Rouse_ ©   (10.12.07 17:12)

Когда отправляла, твоего ответа не видела.
Правильно !
:)


 
Rouse_ ©   (2007-12-10 17:14) [10]


> Верных ответов, пока, нет :)

Проверил - показывает двойку :)


 
Rouse_ ©   (2007-12-10 17:15) [11]


> вторая функция возвратит 3

Нет, т.к. param уже будет не 0 а единица :)


 
Palladin ©   (2007-12-10 17:16) [12]

млин... условие if забыл... розыч, посыпаю голову пеплом
2 возвратит


 
Riply ©   (2007-12-10 17:16) [13]

>[5] Сергей М. ©   (10.12.07 17:11)
> Бедняга).. Целых пол-дня !!
> Нет бы сразу пройтись отладчиком и выяснить, где таятся грабли)

В свое оправдание скажу, что настоящая ситуация выглядит не совсем так :)
Это ее суть :)


 
Reindeer Moss Eater ©   (2007-12-10 17:16) [14]

2


 
Riply ©   (2007-12-10 17:18) [15]

Я когда искала ошибку, на автомате полагала, что
сначала выполниться Funct1, а потом Funct2


 
Riply ©   (2007-12-10 17:20) [16]

> [12] Palladin ©   (10.12.07 17:16)
> [14] Reindeer Moss Eater ©   (10.12.07 17:16)

Я всегда говорила, что настоящие программисты здесь :)
Но Rouse_ первым увидел подвох :)


 
Rouse_ ©   (2007-12-10 17:21) [17]


> на автомате полагала, что
> сначала выполниться Funct1, а потом Funct2

Так оно так и происходит :) Сначала первая выполняется а потом вторая :)


 
Palladin ©   (2007-12-10 17:22) [18]


> Riply ©   (10.12.07 17:20) [16]

:) я if не учел при внутреннемозговом исполнениии...
вывод: пиво - враг интерпритации действий...


 
Rouse_ ©   (2007-12-10 17:22) [19]


> пиво - враг интерпритации действий...

Ты на работе под пивом кодишь? Суров... :)


 
Сергей М. ©   (2007-12-10 17:23) [20]


> Riply ©   (10.12.07 17:16) [13]


> настоящая ситуация выглядит не совсем так


А неважно как она выглядит)
Трассировка мгновенно расставила бы все точки над i)


 
Palladin ©   (2007-12-10 17:23) [21]


> Так оно так и происходит :) Сначала первая выполняется а
> потом вторая :)

:) вот только во второй значение уже другое ибо var...
диагноз: ай ай ай... :)


 
Palladin ©   (2007-12-10 17:24) [22]


> Rouse_ ©   (10.12.07 17:22) [19]

а кто сказал что я сейчас кодю? :) я в форуме сидю... :)

вот... пытался интерпретировать... и не замечая мелких деталей рванувшись к цели - промазал :)


 
Riply ©   (2007-12-10 17:24) [23]

> [17] Rouse_ ©   (10.12.07 17:21)

> Так оно так и происходит :) Сначала первая выполняется а потом вторая :)

???

> [18] Palladin ©   (10.12.07 17:22)
> :) я if не учел при внутреннемозговом исполнениии...
> вывод: пиво - враг интерпритации действий...

:)


 
guav ©   (2007-12-10 17:26) [24]

Напоминает
int i = 5;
cout << ++i + ++i;
где разные компиляторы разный результат дают


 
Rouse_ ©   (2007-12-10 17:26) [25]


> Riply ©   (10.12.07 17:24) [23]
> ???

Ну ты посмотри в отладчике, при вызове ShowMessage сначала происходит выполнение первой функции, потом передается управление на вторую, потом конкатенация и вызов IntToStr :)

Unit38.pas.118: ShowMessage(IntToStr(Funct1(Param) + Funct2(Param)));
0045EF3F 8D45FC           lea eax,[ebp-$04]
0045EF42 E8C1FFFFFF       call Funct1
0045EF47 8BD8             mov ebx,eax
0045EF49 8D45FC           lea eax,[ebp-$04]
0045EF4C E8C3FFFFFF       call Funct2
0045EF51 03D8             add ebx,eax
0045EF53 8BC3             mov eax,ebx
0045EF55 8D55F8           lea edx,[ebp-$08]
0045EF58 E8AF98FAFF       call IntToStr


 
stone ©   (2007-12-10 17:30) [26]


> Riply ©   (10.12.07 17:08)  

Задачку про буратино и яблоки знаешь?


 
DiamondShark ©   (2007-12-10 17:34) [27]


> Чур Delphi не пользоваться :)

А без этого -- гадание на кофейной гуще.
Потому что порядок, в котором вызовутся функции никем не гарантирован.


> guav ©   (10.12.07 17:26) [24]
> Напоминает
> int i = 5;
> cout << ++i + ++i;
> где разные компиляторы разный результат дают

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


 
Palladin ©   (2007-12-10 17:36) [28]


> DiamondShark ©   (10.12.07 17:34) [27]

Эт почему не гарантирован? Какой то delphi компилятор строит выполнение выражения справа налево чтоли?


 
Riply ©   (2007-12-10 17:36) [29]

> [26] stone ©   (10.12.07 17:30)
> Задачку про буратино и яблоки знаешь?

Неа.

> [27] DiamondShark ©   (10.12.07 17:34)
> Потому что порядок, в котором вызовутся функции никем не гарантирован.

А можно аргументировать ?


 
Rouse_ ©   (2007-12-10 17:39) [30]

Кстати, а у кого FreePascal есть? Проверьте там очередность вызова.


 
Riply ©   (2007-12-10 17:44) [31]

> [25] Rouse_ ©   (10.12.07 17:26)
> Ну ты посмотри в отладчике,

Смотрю и не могу понять, почему тогда возвращается 2 ?


 
Palladin ©   (2007-12-10 17:46) [32]


> Rouse_ ©   (10.12.07 17:39) [30]

точно такая же... но я бы удивился если бы это было не так..


> Riply ©   (10.12.07 17:44) [31]

потому что параметр передан по ссылке, а не по значению... соответственно когда выполнилась функция func1 само значение param уже 1 соответственно при переходе к исполнению func2 оно тоже 1


 
Palladin ©   (2007-12-10 17:47) [33]

param имеется ввиду сама переменная парам а не та что в параметрах


 
Германн ©   (2007-12-10 17:47) [34]


> Смотрю и не могу понять, почему тогда возвращается 2 ?
>

Я тоже не могу понять.


 
Германн ©   (2007-12-10 17:49) [35]


> Palladin ©   (10.12.07 17:47) [33]
>
> param имеется ввиду сама переменная парам а не та что в
> параметрах
>

А как же АСМ в Rouse_ ©   (10.12.07 17:26) [25]?


 
Riply ©   (2007-12-10 17:51) [36]

> [32] Palladin ©   (10.12.07 17:46)
> потому что параметр передан по ссылке, а не по значению...
>соответственно когда выполнилась функция func1 само значение param уже 1
> соответственно при переходе к исполнению func2 оно тоже 1

но тогда(при переходе к исполнению func2 оно тоже 1) func2 ничего бы не изменила и мы бы увидели 1


 
Rouse_ ©   (2007-12-10 17:51) [37]


> Смотрю и не могу понять, почему тогда возвращается 2 ?

Ок, разжую :)

Unit38.pas.117: Param := 0;
0045EF3A 33C0             xor eax,eax // чистим Param
0045EF3C 8945FC           mov [ebp-$04],eax // помещает его на стек
Unit38.pas.118: ShowMessage(IntToStr(Funct1(Param) + Funct2(Param)));
0045EF3F 8D45FC           lea eax,[ebp-$04] // готовим ссылку на параметр
0045EF42 E8C1FFFFFF       call Funct1 // дергаем функцию
0045EF47 8BD8             mov ebx,eax // сохраняем результат функции во временном регистре (в ebp-$04 также лежит единица, т.к. ByRef)
0045EF49 8D45FC           lea eax,[ebp-$04] // готовим ссылку на параметр
0045EF4C E8C3FFFFFF       call Funct2 // дергаем вторую функцию
// она также вернула единицу т.к. не выполнилось условие if Param = 0 then
0045EF51 03D8             add ebx,eax // складываем оба результата
0045EF53 8BC3             mov eax,ebx // ну а дальше IntToStr и ShowMessage
0045EF55 8D55F8           lea edx,[ebp-$08]
0045EF58 E8AF98FAFF       call IntToStr
0045EF5D 8B45F8           mov eax,[ebp-$08]
0045EF60 E87BE5FCFF       call ShowMessage


 
Rouse_ ©   (2007-12-10 17:52) [38]


> func2 ничего бы не изменила и мы бы увидели 1

Не изменила - она вернула то, что ей было переданно, а передано ей было уже 1 а не ноль :)


 
Palladin ©   (2007-12-10 17:54) [39]


> Riply ©   (10.12.07 17:51) [36]

ну мля... в параметрах исполнения func один передается не значение 0, а ссылка на саму переменную, и именна сама переменная после отработки функции меняет значение, после идет исполнение func два, которой уже передано (и кстати не важно как var или const или просто в стек засунуто) значение 1 потому что func один уже поменяла значение...


 
Riply ©   (2007-12-10 17:54) [40]

> [37] Rouse_ ©   (10.12.07 17:51)
> Ок, разжую :)

Спасибо.


 
Mystic ©   (2007-12-10 17:56) [41]

По хорошему это UB


 
Riply ©   (2007-12-10 17:58) [42]

Ну вот и встало все на свои места.
Люблю когда так :)


 
Palladin ©   (2007-12-10 17:58) [43]

это должно быть ясно и без ASM кода, бо он может различаться в зависимости от компилятора, само использование Var в декларации параметров это подразумевает, что значение самой переменной будет менятся тут же сию секунду как только произошло присваивание...


 
@!!ex ©   (2007-12-10 17:58) [44]

> А можно аргументировать ?

А кем он гарантирован..
Я в документации не нашел, описания последовательности обработки вызовов.

P.S.
Такие функции Must Die. IMHO


 
DiamondShark ©   (2007-12-10 18:00) [45]


> Palladin ©   (10.12.07 17:36) [28]
>
> > DiamondShark ©   (10.12.07 17:34) [27]
>
> Эт почему не гарантирован? Какой то delphi компилятор строит
> выполнение выражения справа налево чтоли?

"Вы видели у меня вывеску "Склад мёртвых нигеров"? Нет? А вы знаете почему вы её не видели?"

Вы видели в спецификации языка слова "арифметические выражения вычисляются в строго определённом порядке"?

Разумеется, конкретный компилятор конкретное выражение каждый раз скомпилирует одинаково, потому что программа компилятора дерминирована.
Но это не значит, что для другого выражения даже тот же самый компилятор выберет точно такой же порядок.

Это было бы очень глупым, с точки зрения оптимизации, требованием.

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

А вот для булевских выражений (в отличие от арифметических!) чётко расписан и порядок, и то, от чего он зависит.


> Riply ©   (10.12.07 17:36) [29]
> А можно аргументировать ?

Аргументировать отсутствие? Вы серьёзно?


 
Palladin ©   (2007-12-10 18:08) [46]


> DiamondShark ©   (10.12.07 18:00) [45]

А не казалось ли тебе, что порядок исполнения выражения слева направо является стандартом де-факто и что работа компилятора отличающаяся от стандрата должна быть документирована на первых же страницах мануала? судя по твоим словам о оптимизации, я не могу гарантировать что код:

func1;
func2;

пойдет именно в таком порядке.

составное выражение вызовов на самом деле разбирается именно слева на право, бо:

r:=func1+func2

тождественно

tmp1:=func1;
tmp2:=func2;
r:=tmp1+tmp2;


 
stone ©   (2007-12-10 18:08) [47]


> Riply ©   (10.12.07 17:36) [29]
> > [26] stone ©   (10.12.07 17:30)
> > Задачку про буратино и яблоки знаешь?
>
> Неа.

Буратино дали два яблока. Потом еще два. Сколько яблок теперь у Буратино?
4 - не правильный ответ.
Правильный ответ - неизвестно, т.к. не известно, сколько я блок было в начале.
Мораль: Всегда инициализируйте переменные.


 
Palladin ©   (2007-12-10 18:11) [48]


> stone ©   (10.12.07 18:08) [47]

переменная инициализирована... задача не к месту


 
Celades ©   (2007-12-10 18:11) [49]


> Разумеется, конкретный компилятор конкретное выражение каждый
> раз скомпилирует одинаково, потому что программа компилятора
> дерминирована.

Очень спорное заявление. В зависимости от контекста в котором это выражение используется, может меняться и генерированный компилятором код.


 
Riply ©   (2007-12-10 18:15) [50]

Усложним задачку:
Что теперь нам выдаст ShowMessage и почему ?

type
TStreamHlp = class Helper for TStream
 function Write_DWord(const Value: DWord): DWord;
 function Write_String(const Value: string): DWord;
 function Read_String: string;
 function Write_StringAndInt(const aStrValue: string; const Value: integer): DWord;
end;

function TStreamHlp.Write_DWord(const Value: DWord): DWord;
begin
Result := Write(Value, SizeOf(DWord));
end;

function TStreamHlp.Write_String(const Value: string): DWord;
var
ValLen: DWord;
begin
ValLen := Length(Value);
Result := Write(ValLen, SizeOf(DWord));
if ValLen > 0 then inc(Result, Write(Pointer(Value)^, ValLen));
end;

function TStreamHlp.Read_String: string;
var
cbData: DWord;
begin
Read(cbData, SizeOf(DWord));
SetLength(Result, cbData);
if cbData > 0 then Read(Pointer(Result)^, cbData);
end;

function TStreamHlp.Write_StringAndInt(const aStrValue: string; const Value: integer): DWord;
begin
Result := Write_String(aStrValue) + DWord(Write(Value, SizeOf(Integer)));
end;

procedure TMainForm.SpeedButton1Click(Sender: TObject);
var
Stream: TMemoryStream;
Buf: string;
begin
Buf := "integer";
with TMemoryStream.Create do
 try
  Write_StringAndInt(Buf, 5);
  Position := 0;
  Buf := Read_String;
  ShowMessage(Buf);
 finally
  Free;
 end;
end;


 
Riply ©   (2007-12-10 18:16) [51]

Sorry. Забыла код выделить :(


 
@!!ex ©   (2007-12-10 18:19) [52]

> [46] Palladin ©   (10.12.07 18:08)

Бред.
"ОТ перемены мест слагаемых сумма не меняется." (С) 2 класс, средней школы.
Соотвественно компилятору никто не запрещает выполнять вычисление слагаемых в ЛЮБОМ порядке, если это не документировано. А это - не докуменированно.


 
Palladin ©   (2007-12-10 18:22) [53]


> @!!ex ©   (10.12.07 18:19) [52]

а при чем тут знак + ? ты самую первую задачу то читал? как то 2 класс средней школы сюда не вписывается


 
@!!ex ©   (2007-12-10 18:26) [54]

> [53] Palladin ©   (10.12.07 18:22)

по правилам второго класса:
ShowMessage(IntToStr(Funct1(Param) + Funct2(Param)));
равно
ShowMessage(IntToStr(Funct2(Param) + Funct1(Param)));

Я лично о порядке выолнения функций говорю, а вы?


 
Palladin ©   (2007-12-10 18:30) [55]


> @!!ex ©   (10.12.07 18:26) [54]


function Funct1(var Param: integer): integer;
begin
If param<1 then inc(Param, 1);
Result := Param;
end;

function Funct2(var Param: integer): integer;
begin
inc(Param, 2);
Result := Param;
end;

чему же будет равно

ShowMessage(IntToStr(Funct1(Param) + Funct2(Param))

и чему будет равно

ShowMessage(IntToStr(Funct2(Param) + Funct1(Param))

при инициализации param:=0

:)


 
Riply ©   (2007-12-10 18:30) [56]

> [54] @!!ex ©   (10.12.07 18:26)

А если в Funct2 будет не inc(Param, 2) а inc(Param, 20) ?
Результаты тоже совпадут ?


 
Palladin ©   (2007-12-10 18:33) [57]


> Riply ©   (10.12.07 18:30) [56]

да :) условие if мешает


 
Palladin ©   (2007-12-10 18:34) [58]


> Riply ©   (10.12.07 18:30) [56]

прошу прощенья... так... все... надо сосредоточится... :)


 
DiamondShark ©   (2007-12-10 18:34) [59]


> Celades ©   (10.12.07 18:11) [49]

...в конкретном контексте...
далее по тексту.

Кстати, да.
Тем меньше оснований закладываться на какой-либо порядок.


> Palladin ©   (10.12.07 18:08) [46]
>
> А не казалось ли тебе, что порядок исполнения выражения
> слева направо является стандартом де-факто

Нет. Не казалось.
В арифметике A + B не зависит от того, в какой последовательности вычислилось A и B.


> и что работа
> компилятора отличающаяся от стандрата должна быть документирована
> на первых же страницах мануала?


Какого ещё стандарта? Стандарта на арифметические выражения? Так в арифметике A + B не зависит от порядка вычисления A и B.


> судя по твоим словам о оптимизации, я не могу гарантировать что код:
>
> func1;
> func2;


Передёргиваешь. Я говорю о выражениях. То, что ты написал не выражение, а последовательность операторов. А для последовательности операторов в спецификации языка явно сказано, что они выполняются в порядке текстуального следования.


> составное выражение вызовов на самом деле разбирается именно
> слева на право, бо:


"Разбирается" -- не значит "исполняется".
После того, как я разобрал выражение и построил синтаксическое дерево, я могу выбрать произвольный порядок исполнения ветвей. Например, по критерию количества временных переменных.


> r:=func1+func2
>
> тождественно
>
> tmp1:=func1;
> tmp2:=func2;
> r:=tmp1+tmp2;


Сможешь объяснить, почему не
tmp2:=func2;
tmp1:=func1;
r:=tmp1+tmp2;

?

Только поту что ты привык читать слева-направо?
Так машине пофиг. У неё привычек не бывает.

Вот тебе другой пример

(d + e) / (a + b + c)

При компиляции выгоднее вычислить сначала длинную часть (делитель), а потом делимое. Из-за особенности системы команд.
Потребуется меньше промежуточных переменных.
Если оптимизатор этого не сделает, значит это плохой оптимизатор.


 
DiamondShark ©   (2007-12-10 18:36) [60]


> @!!ex ©   (10.12.07 18:19) [52]
> > [46] Palladin ©   (10.12.07 18:08)
>
> Бред.
> "ОТ перемены мест слагаемых сумма не меняется." (С) 2 класс,
>  средней школы.

А тут даже коммутативность ни при чём. Можешь вполне считать все операции некоммутативными, сказанного это не изменит ничуть.


 
Palladin ©   (2007-12-10 18:46) [61]


> DiamondShark ©   (10.12.07 18:34) [59]

мне казалось речь идет не об обработке значений переменных, а именно о вызовах функций... а вообще интересно, речь о машине или о компиляторах? к сожалению у меня нет сейчас доступа в инет кроме delphimaster и подтвердить правило очередности исполнений, приведя ссылки, я не могу...

ну а, по поводу "несказанного" правила слева на право, боюсь, если бы компиляция вызовов в разных компиляторах происходила бы по разному, то писать программы людям было бы не возможно без документирования сего факта, бо это привело бы к самым непредсказуемым последствиям для непосвященных...

бо стандарт де факто...


 
DiamondShark ©   (2007-12-10 18:47) [62]


> DiamondShark ©   (10.12.07 18:34) [59]

Кстати, при компиляции под стековую машину (JVM, MSIL или даже наш родной FPU) ещё очевиднее выгодность не фиксировать порядок вычисления ветвей, а именно выбирать его по критерию минимальности промежуточных значений.

Врочем, для регистровой машины с шибко малочисленными и неравноправными регистрами, каковой является х86, это тоже актуально.

Ни один разработчик ЯВУ в здравом уме не будет фиксировать порядок выполнения арифметических операций.
(Разработчики Си не были в здравом уме, но и они не зафиксировали. Хотя им, из-за обилия операций с побочным эффектом, как раз надо было бы).


 
Palladin ©   (2007-12-10 18:48) [63]


> Сможешь объяснить, почему не tmp2:=func2;tmp1:=func1;r:=tmp1+tmp2;
> ?

смогу... именно по причине...


> Palladin ©   (10.12.07 18:30) [55]


 
@!!ex ©   (2007-12-10 18:49) [64]

> [61] Palladin ©   (10.12.07 18:46)
> бо стандарт де факто...


Ни разу в жизни не видел кода в практическом применении, результат работы которого зависил от того, в каком виде выполняется: Func1()+Func2() или Func2()+Func1(). ИМХО если писать зависимый код, отгребешь СТОЛЬКО багов, что не найдешь их ввек.


 
Gydvin ©   (2007-12-10 18:52) [65]


> @!!ex ©   (10.12.07 18:26) [54]
> > [53] Palladin ©   (10.12.07 18:22)по правилам второго
> класса:ShowMessage(IntToStr(Funct1(Param) + Funct2(Param)));
> равноShowMessage(IntToStr(Funct2(Param) + Funct1(Param)));
>


Ну и чему будет равно и в том и в том случае: ))


 
Romkin ©   (2007-12-10 18:56) [66]

Напоминаю: для операторов порядок вычисления строго документирован:
"An operator with higher precedence is evaluated before an operator with lower precedence, while operators of equal precedence associate to the left".


 
DiamondShark ©   (2007-12-10 18:57) [67]


> Palladin ©   (10.12.07 18:46) [61]


> приведя ссылки, я не могу...

Когда я читал Вирта "Паскаль. Сообщение. Описание языка" я точно помню, что там было написано про порядок арифметических выражений "зависит от реализации" или что-то в этом роде. К сожалению, тоже не могу подтвердить, потому что книжка бумажная и не помню где лежит.


> ну а, по поводу "несказанного" правила слева на право, боюсь,
>  если бы компиляция вызовов в разных компиляторах происходила
> бы по разному, то писать программы людям было бы не возможно
> без документирования сего факта

Если не сказано явно, значит считается "неопределено", или "зависит реализации". Я думал, что именно такая методика интерпретации документации является не только "стандартом де факто", но и единственно разумной.


> бо это привело бы к самым непредсказуемым последствиям для
> непосвященных...

Только в результате использования операций или функций с сайд-эффектом.
А это само по себе мастдай.


> бо стандарт де факто...

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


 
DiamondShark ©   (2007-12-10 18:59) [68]


> Romkin ©   (10.12.07 18:56) [66]

Это из другой оперы.

Считай, что у нас все операторы равноприоритетны и мы явно расставили скобки.
Ничего не изменится.


 
Palladin ©   (2007-12-10 19:00) [69]


> @!!ex ©   (10.12.07 18:49) [64]

именно, что бы не было странных багов так и принято слева на право, где вообще в русском языке сказано правило, что читать текст нужно слева на право, а не по диагонали снизу вверх..

ну а то что ни разу не видел... ну... повезло... не писал ты под ДОС занимаясь экономией на каждом вызове...


> Gydvin ©   (10.12.07 18:52) [65]

уточнение функций в [55] видел?


 
DiamondShark ©   (2007-12-10 19:03) [70]


> Palladin ©   (10.12.07 18:48) [63]

Ты ничего не объяснил.
Ты показал, как конкретный компилятор ведёт себя на конкретном классе выражений.

Вопрос был другой: почему он должен так себя вести?


 
Palladin ©   (2007-12-10 19:04) [71]


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

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


 
@!!ex ©   (2007-12-10 19:05) [72]

> ну а то что ни разу не видел... ну... повезло... не писал
> ты под ДОС занимаясь экономией на каждом вызове...

Я пишу на ассемблере, и там делаю вызовы тогда когда мне это нужно.
А если я пишу на Паскале, то пишу так, чтобы не зависить от последовательности. Ку?


 
DiamondShark ©   (2007-12-10 19:06) [73]


> не писал ты под ДОС занимаясь экономией на каждом вызове

Ха-ха!
А экономия сводилась, часом, не к эквивалентным преобразованиям выражений вручную?
;))))
Т.е. тем, чем должен заниматься умный компилятор, а ты хочешь ему это запретить.


 
Gydvin ©   (2007-12-10 19:07) [74]


> > Gydvin ©   (10.12.07 18:52) [65]
>
> уточнение функций в [55] видел?


с 55 согласен результат будет один и тот же. Хотя Funct1 можно было оставить без изменений )

Только 54 было раньше 55...


 
Palladin ©   (2007-12-10 19:07) [75]


> DiamondShark ©   (10.12.07 19:03) [70]

он не должен себя вести, это от него ожидается
я же не утверждаю, что это закон! я утверждаю, что это принято повсеместно, а тот факт что он себя так не ведет должен отражаться в документации


 
TUser ©   (2007-12-10 19:09) [76]

Однокамушкин тут такой же пример давал. В зависимости от компилятора порядок вычисления выражения - разный, даже fpc и fpc -Mdelphi дают разный результат.


 
@!!ex ©   (2007-12-10 19:11) [77]

> [75] Palladin ©   (10.12.07 19:07)

Как он себя ведет - отражено в документации.
А вот что он ведет себя не так, как ВАМ этого ХОЧЕТЬСЯ, не отражено.
ТО что не определено, то - НЕОПРЕДЕЛЕНО. И при работе с языком есть только один документ: Описание Языка, все остальные стандарты никакого отношения к языку не имеет, это все ваши домыслы.


 
Gydvin ©   (2007-12-10 19:11) [78]


> с 55 согласен результат будет один и тот же.


Да и то только при условии что во второй функции прибавляемое число в два раза больше чем в первой


 
Palladin ©   (2007-12-10 19:13) [79]


> Как он себя ведет - отражено в документации.

ну так в том то и дело, как уже сказал DiamondShark это не отражено в документации, и ожидается принятое, человеческое...


 
DiamondShark ©   (2007-12-10 19:14) [80]


> Palladin ©   (10.12.07 19:07) [75]
>
> он не должен себя вести, это от него ожидается

Так это проблемы ожидающего.


> я же не утверждаю, что это закон! я утверждаю, что это принято
> повсеместно,

Не принято. Примеры уже приводили.


> а тот факт что он себя так не ведет должен
> отражаться в документации

Это насилие над логикой: перечислять отсутствующие свойства.


 
Gydvin ©   (2007-12-10 19:14) [81]

пример на документацию любого языка программирования где сначала будет выполняться второй оператор, а затем первый в контексте сабжа есть?


 
DiamondShark ©   (2007-12-10 19:16) [82]


> Palladin ©   (10.12.07 19:13) [79]
>
> > Как он себя ведет - отражено в документации.
>
> ну так в том то и дело, как уже сказал DiamondShark это
> не отражено в документации, и ожидается принятое, человеческое.

Как уже сказал DiamondShark, принятое, человеческое совсем другое.


 
@!!ex ©   (2007-12-10 19:16) [83]

> [79] Palladin ©   (10.12.07 19:13)

Да в том то и дело. Что НЕЛЬЗЯ ничего ожидать, если это не утверждено в стандарте.
Нет default значения. Есть НЕОПРЕДЕЛЕННОЕ значение. И когда программист этого не учитывает, получает:
"Прикол с борландовским Си, когда выражение с сайд-эффектами давало разные результаты в зависимости от ключей компилятора -- притча во языцех."[67]


 
@!!ex ©   (2007-12-10 19:17) [84]

> [81] Gydvin ©   (10.12.07 19:14)

На примеры документация врядли есть. Но и обратной документации нету тоже.


 
Gydvin ©   (2007-12-10 19:21) [85]

А негласные стандарты не учитываются?
Зачем переливать из пустого в порожнее и изыскивать то, что в природе не существует?


 
@!!ex ©   (2007-12-10 19:22) [86]

> [85] Gydvin ©   (10.12.07 19:21)

Как можно в формализованной структуре учитывать неформализованные стандарты?


 
guav ©   (2007-12-10 19:23) [87]

Ожидать определённый порядок выражений по разные стороны бинароного оператора - это то же что и ожидать определённый порядок оценки параметров функции.


 
Gydvin ©   (2007-12-10 19:24) [88]

Хотябы тем что это все писалось людьми и для людей. Иначе разбродс...


 
guav ©   (2007-12-10 19:30) [89]

> то же что и ожидать определённый порядок оценки параметров
> функции.

Кстати, думаю на функциях cdecl или stdcall легко будет получить "противоинтуитивный" порядок, т.к. оптимизатор может захотеть расположить оценивание в порядке размещения в стеке.


 
@!!ex ©   (2007-12-10 19:31) [90]

> [88] Gydvin ©   (10.12.07 19:24)

Форт кем писался? :))


 
Palladin ©   (2007-12-10 19:31) [91]

то, что я не верблюд вообще доказать сложно...


 
Gydvin ©   (2007-12-10 19:34) [92]


> @!!ex ©   (10.12.07 19:31) [90]
> > [88] Gydvin ©   (10.12.07 19:24)Форт кем писался? :))


Ух ты доказательства нашлись :0)
И что там? Не смотрел язык


 
guav ©   (2007-12-10 19:36) [93]

В С++ порядок оценивания гарантируется только для встроенных логических and и or, и оператора запятая (для and и or гарантирована также сокращённая оценка). Для остальных бинарных операторах ничего не подразумевается.
Может стоит посмотреть в справке Delphi насчёт логических операторов, для них тоже наверное гарантируется порядок, и там может указано и про остальные ?


 
Григорьев Антон ©   (2007-12-10 19:39) [94]

Этот прикол с порядком операндов известен давно: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=631

И в этом форуме мы его месяца четыре назад обсуждали. Тогда выяснилось, что в тестовом примере FreePascal, в отличие от Delphi, по умолчанию сначала вычислил первый аргумент, а затем второй, но когда при компиляции включили опцию совместимости с Delphi, то тоже вычислял сначала второй аргумент, потом первый.


 
korneley ©   (2007-12-10 19:41) [95]


> @!!ex ©   (10.12.07 19:31) [90]
Чарльз Мур


 
Anatoly Podgoretsky ©   (2007-12-10 19:43) [96]

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

> An operator with higher precedence is evaluated before an
> operator with lower precedence, while operators of equal
> precedence associate to the left. Hence the expression
>
> X + Y * Z
>
> multiplies Y times Z, then adds X to the result; * is performed
> first, because is has a higher precedence than +. But
>
> X - Y + Z
>
> first subtracts Y from X, then adds Z to the result; - and
> + have the same precedence, so the operation on the left  is performed first.


 
Palladin ©   (2007-12-10 19:49) [97]


> Anatoly Podgoretsky ©   (10.12.07 19:43) [96]

DiamondShark сопротивляется и советует не путать теплое с мягким


 
@!!ex ©   (2007-12-10 19:51) [98]

> [97] Palladin ©   (10.12.07 19:49)

Да не вопрос, раз в документации написано, то значит так и должно быть.
Лично я спорил не об этом. А о том, что если в документации этого НЕТ, значит ничего подразумевать НЕЛЬЗЯ.


 
Mystic ©   (2007-12-10 19:52) [99]

> Anatoly Podgoretsky ©   (10.12.07 19:43) [96]

Порядок выполнения операций определен, но где же порядок вычисления операндов?


 
@!!ex ©   (2007-12-10 19:53) [100]

> [99] Mystic ©   (10.12.07 19:52)

Кстати да...


 
Palladin ©   (2007-12-10 19:56) [101]


> @!!ex ©   (10.12.07 19:51) [98]

а раз ничего подразумевать нельзя, то нельзя и работать с компилятором... так? мало ли чего он еще неподразумевает... или я не прав? вдруг он начнет компилировать задом наперед, бо быстрее будет... это ж не указано в документации... как он будет компилировать...


 
Anatoly Podgoretsky ©   (2007-12-10 20:00) [102]


> Порядок выполнения операций определен, но где же порядок
> вычисления операндов?

О каких операндах ты говоришь
ShowMessage(IntToStr(Funct1(Param) + Funct2(Param)));Когда у Funct1, Funct2 и у IntToStr по одному операнду.
Здесь единственная проблема, что это не функция, поскольку изменяет значения за пределами функции, в итоге побочные эффекты. По другому это не детерминированая "функция".


 
@!!ex ©   (2007-12-10 20:06) [103]

> [101] Palladin ©   (10.12.07 19:56)

Не надо. В документации как раз указано более чем достаточно информации для того, чтобы можно было однозначно предсказывать поведение кода не делая при этом никаких домыслов.


 
Palladin ©   (2007-12-10 20:11) [104]


> @!!ex ©   (10.12.07 20:06) [103]

приведи


 
@!!ex ©   (2007-12-10 20:30) [105]

> [104] Palladin ©   (10.12.07 20:11)

Что привести?


 
Palladin ©   (2007-12-10 20:35) [106]


> @!!ex ©   (10.12.07 20:30) [105]


Более чем достаточное содержание документации, которое убедит меня в том, что я могу однозначно предсказывать поведение кода не делая при этом никаких домыслов. То есть я смело напишу a:=funct1(v)/funct2(v)
и буду уверен что выполнится funct1, а потом funct2, ведь я подразумеваю что выполнится funct1, а потом funct2. соответственно результат будет верен.

или ты о чем то другом?


 
@!!ex ©   (2007-12-10 20:49) [107]

> [106] Palladin ©   (10.12.07 20:35)

Сейчас дельфи только качаеться, не могу посмотреть документацию, чтобы привести соответствующие вырезки.
Позднее. Ок?

P.S.
Пример, кстати, полностью попадает под спецификацию Паскаля, если я правильно помню.


 
Palladin ©   (2007-12-10 20:52) [108]


> @!!ex ©   (10.12.07 20:49) [107]

без проблем... хоть я и попробовал пошарится по Object Pascal Reference для D6 на счет порядка вызовов в составных выражениях... безуспешно

как сказал мой друг: "когда дело касается правил языка, я смотрю в стандарт языка, а не в доки на компилятор"

на что я ему ответил: "каждый создает свой язык на основе принятого. и он не обязан следовать семантике и лексике"

Я конечно извиняюсь, но откланяюсь, домой нуна... продолжим завтра... а по поводу:

"Прикол с борландовским Си, когда выражение с сайд-эффектами давало разные результаты в зависимости от ключей компилятора -- притча во языцех"

исключение подтверждает правило...


 
Григорьев Антон ©   (2007-12-10 20:58) [109]

Языки Pascal и Ada позволяют операндам бинарных выражений вычисляться в любом порядке, выбираемом разработчиком средств реализации языка.

Роберт У. Себеста, "Основные концепции языков программирования", 5-е изд.: Пер. с англ. - м.: "Издательский дом Вильямс", 2001
Раздел 6.2.2 "Порядок вычисления операндов", стр. 284


 
Palladin ©   (2007-12-10 21:02) [110]


> Григорьев Антон ©   (10.12.07 20:58) [109]

пока жду машину

Антон, а что ты ожидаешь от
a:=f1(v)/f2(v)
где в обеих функциях параметр передается по ссылке и не заявлено и в документации компилятора вбсолютно вообще ничего не сказано об порядке исполнения вызовов? будешь ли ты делать так или же прибегнешь к:
tmp1:=f1(v);
tmp2:=f2(v);
a:=tmp1/tmp2;
?


 
Сергей Суровцев ©   (2007-12-10 21:14) [111]

>Mystic ©   (10.12.07 19:52) [99]
>Порядок выполнения операций определен, но где же порядок вычисления
>операндов?

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


 
Palladin ©   (2007-12-10 21:32) [112]


> Сергей Суровцев ©   (10.12.07 21:14) [111]

кто сказал? (C) DimondShark


 
Kolan ©   (2007-12-10 21:34) [113]

> [0] Riply ©   (10.12.07 17:08)

Такой код писать иожно вообще умалишится, нахрена делать процедуру-функцию? Что-то одно выбрать нельзя.


 
Григорьев Антон ©   (2007-12-10 21:38) [114]


> Palladin ©   (10.12.07 21:02) [110]
> Антон, а что ты ожидаешь от
> a:=f1(v)/f2(v)

Я и с делением экспериментировал. В простых ситуациях там тоже вторая функция вызывается раньше первой. Поэтому всегда, когда мне нужен гарантированный порядок вычисления операндов, я разношу эти вычисления по разным операторам.


> Сергей Суровцев ©   (10.12.07 21:14) [111]
> Порядок вычисления операндов может быть любым. Но вызов
> функции это еще не операнд.

Не понял этой фразы. Если операндом является функция, то чем вызов функции отличается от вычисления операнда?


 
Сергей Суровцев ©   (2007-12-10 21:53) [115]

>Palladin ©   (10.12.07 21:32) [112]
>кто сказал? (C) DimondShark

Здравый смысл и правила арифметических вычислений. Если все операнды уже однозначно определены, то как бы компилятор их не выполнял, в итоге он обязан следовать этим правилам. Не важно, начнется разбор выражения с начала, конца или середины. До вычисления функция эти операнды еще не определены однозначно.

>Григорьев Антон ©   (10.12.07 21:38) [114]
>Не понял этой фразы. Если операндом является функция, то чем вызов
>функции отличается от вычисления операнда?

Смысл в том, что функция сама по себе выполняет действие и возвращает результат. Она сама не есть операнд. Операнд, участвующий в выражении это тот результат, который она возвратила. Если в выражении несколько ф-й подряд оперируют одним массивом данных с возможностью его модификации, то в зависимости от порядка выполнения ф-й будет разный результат. А этого быть не должно.
Если компилятор ведет себя иначе, не соблюдая порядок вызова ф-й, то это баг. Если он задокументированный, то фича. Но логика становится нездоровой и наверняка приносится в жертву скорости, ибо подобных случаев взаимного влияния функций в выражении немного.


 
Alex Konshin ©   (2007-12-10 22:06) [116]

DiamondShark ©   (10.12.07 18:00) [45]
Единственно верный ответ.
Меня лично несколько удивило, что даже некоторые мастера что-то имеют против этого...

В большинстве языков не задаётся порядок вычисления ни операндов бинарной операции, ни аргументов функции. А потому использовать функции с side effect в таких ситуациях - зло. Хотя и известно, что Delphi выполняет всё слево напрово, но использовать это знание не рекомендуется, т.к. это не задокументировано и потому может измениться в любой момент. Например, если вдруг компилятор научится распараллеливать вычисление операндов, то результат такого выражения будет непредсказуемым. То, что скоро компиляторы так будут делать - я нисколько не сомневаюсь,  потому что ядер скоро будет много, а распаралеллить такое вычисление не так уж и сложно.


 
tesseract ©   (2007-12-10 22:14) [117]


>  То, что скоро компиляторы так будут делать - я нисколько
> не сомневаюсь,  потому что ядер скоро будет много, а распаралеллить
> такое вычисление не так уж и сложно.


В дополнение :

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


 
Alex Konshin ©   (2007-12-10 22:46) [118]

tesseract ©   (10.12.07 22:14) [117]
Результат выполнения машинного кода должен быть один и тот же независимо от того, как процессор его выполняет. Так что какой бы он супер-пупер не был, семантика не должна меняться иначе не будет совместимости с предыдущими поколениями процессоров этого семейства, а она есть.
То есть в случае x86 всё зависит от компилятора, а нет от процессора.


 
DiamondShark ©   (2007-12-10 23:01) [119]


> Palladin ©   (10.12.07 19:56) [101]
>
> а раз ничего подразумевать нельзя, то нельзя и работать
> с компилятором... так? мало ли чего он еще неподразумевает.
> .. или я не прав? вдруг он начнет компилировать задом наперед,
>  бо быстрее будет... это ж не указано в документации...
> как он будет компилировать...

А кстати, пофиг, как он будет компилировать. Ибо явно описано в спецификации языка, что операторы исполняются в порядке текстуального следования. А просматривает текст он пусть хоть в три потока с середины по диагонали.

А про то, как интерпретировать описание, я уже говорил, только никто не слышал. Ну, мне повторить не сложно.
1. Следовать тому, что описано явно.
2. Что не описано явно, считать "зависимым от реализации".
Никто более разумной стратегии не предложил.


 
DiamondShark ©   (2007-12-10 23:09) [120]

Кстати, интересно. Люди, посмотрите, кто может, как компилит выражения Дельфи для НЕТ.
Всё-таки, там стековая машина, значит кодогенератор будет отличаться от нативного х86.


 
Mystic ©   (2007-12-11 16:40) [121]


> О каких операндах ты говоришь
> ShowMessage(IntToStr(Funct1(Param) + Funct2(Param)));Когда
> у Funct1, Funct2 и у IntToStr по одному операнду.


У "+" есть два операнда Funct1(Param) и Funct2(Param). Где указано, в каком порядке они будут вычисляться?

Понятно, что в случае выражений
a + b * c     вначале будет выполняться *, а потом +  (приоритет)
a + b - c     вначале будет выполняться +, а потом -  (левоассоциативность)
похожие правила есть в любом языке программирования.

Но порядок вычисления операндов a, b, c не фиксирован.


 
Anatoly Podgoretsky ©   (2007-12-11 18:34) [122]

> Mystic  (11.12.2007 16:40:01)  [121]

> a + b - c     вначале будет выполняться +, а потом -  (левоассоциативность)
> похожие правила есть в любом языке программирования.

Из справки

> Because functions return a value, function calls are expressions.


 
guav ©   (2007-12-11 21:40) [123]

> [122] Anatoly Podgoretsky ©   (11.12.07 18:34)

Угадайте что напишет программа:

program Project2;

{$APPTYPE CONSOLE}

uses
 SysUtils;

function F1(): string;
begin
 Write("First ");
 Result := "Third ";
end;

function F2(): string;
begin
 Write("Second ");
 Result := "Fourth";
end;

procedure F3(X1: string; X2: string = "");
begin
 WriteLn;
end;

begin
 WriteLn(F1(), F2());
 F3(F1(), F2());
 F3(F1() + F2());
 ReadLn;
end.


 
tesseract ©   (2007-12-11 22:30) [124]


> Кстати, интересно. Люди, посмотрите, кто может, как компилит
> выражения Дельфи для НЕТ


В CLR компилит. Исполнение обеспечивает именно CLR. Ее прикол.


> Результат выполнения машинного кода должен быть один и тот
> же независимо от того, как процессор его выполняет. Так
> что какой бы он супер-пупер не был, семантика не должна
> меняться иначе не будет совместимости с предыдущими поколениями
> процессоров этого семейства, а она есть.То есть в случае
> x86 всё зависит от компилятора, а нет от процессора.


Вторая фукнция может выполниться раньше первой. Хотя черт знает - скорее всего ты прав, хотя NTVDM запросто искажает результат.


 
Мазут Береговой ©   (2007-12-11 23:06) [125]

Кстати, я не спец в Delphi, но вопрос, есть ли указание по передаче параметров в функцию/процедуру в Delphi - по ссылке или по значению? Вот как в C# если ref то по ссылке и значение внешней переменной меняется. Если нет ref, то по значению... А как в Delphi?


 
DVM ©   (2007-12-11 23:08) [126]


> А как в Delphi?

var


 
Мазут Береговой ©   (2007-12-11 23:13) [127]

Понял! :-) Спасибо.


 
Anatoly Podgoretsky ©   (2007-12-11 23:30) [128]

> Мазут Береговой  (11.12.2007 23:06:05)  [125]

В Дельфи три метода передаче, по значению (без модификатора), по ссылке с возможностью изменения (модификатор var) и по ссылке без возможности изменения (модификатор const) .


 
DVM ©   (2007-12-11 23:53) [129]


> Anatoly Podgoretsky ©   (11.12.07 23:30) [128]

Еще out есть. Тоже вроде по ссылке с возможностью изменения.


procedure p(out a: integer);
begin
 inc(a);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 b: integer;
begin
 b:= 1;
 p(b);
 caption := inttostr(b);
end;


 
Anatoly Podgoretsky ©   (2007-12-11 23:55) [130]

> DVM  (11.12.2007 23:53:09)  [129]

IN/OUT это разновидности var/const


 
DVM ©   (2007-12-11 23:57) [131]


> IN

Что это?


 
Мазут Береговой ©   (2007-12-11 23:58) [132]

Спасибо. :-)


 
Anatoly Podgoretsky ©   (2007-12-12 00:02) [133]

> DVM  (11.12.2007 23:57:11)  [131]

Параметр только для чтения, не помню есть ли этот модификатор. Аналогично const


 
DVM ©   (2007-12-12 00:07) [134]


> не помню есть ли этот модификатор

В D7 нет точно. Ругается на него. Точнее зарезервированное слово есть, но оно для другого.


 
guav ©   (2007-12-12 00:21) [135]

> [128] Anatoly Podgoretsky ©   (11.12.07 23:30)

> и по ссылке без возможности изменения (модификатор const).

const передаёт по значению, кроме нетипизированых параметров и параметров которые и без модификатора идут по ссылке.


 
Anatoly Podgoretsky ©   (2007-12-12 00:31) [136]

> guav  (12.12.2007 00:21:15)  [135]

Разница есть.

Например для string var это указатель на указатель, а const это указатель или непосредственное значения (для простых типов) без возможности изменения. Без модификатора это то же просто указатель для string или временная копия для некоторых типов, например статических массивов.


 
guav ©   (2007-12-12 00:36) [137]

> Разница есть.

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

Const это ссылка, это такой же миф как и определённый порядок F1 и F2 в F1() + F2()

Вот кстати код, в котором в D7 сначала вторая вызывается:

program Project2;

{$APPTYPE CONSOLE}

uses
SysUtils;

function F1(): Integer;
begin
Write("First ");
Result := 0;
end;

function F2(X, Y: Integer): Integer;
begin
Write("Second ");
Result := 0;
end;

procedure F3(X: Integer);
begin
end;

begin
F3(F1() + F2(1, 2));
ReadLn;
end.



Страницы: 1 2 3 4 вся ветка

Форум: "Прочее";
Текущий архив: 2008.01.20;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.86 MB
Время: 0.051 c
15-1197555361
Dennis I. Komarov
2007-12-13 17:16
2008.01.20
MUI


2-1197922608
istok
2007-12-17 23:16
2008.01.20
Overflow ...


9-1165965583
Vladimir1984
2006-12-13 02:19
2008.01.20
Как выставить на поверхности Карты высот числовые зачения?


2-1197996711
new_user )
2007-12-18 19:51
2008.01.20
недопонимаю...


2-1197979576
istok
2007-12-18 15:06
2008.01.20
верна ли функция





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский