Форум: "Прочее";
Текущий архив: 2008.01.20;
Скачать: [xml.tar.bz2];
ВнизРезультат трехчасовых поисков ошибки в проекте :) Найти похожие ветки
← →
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]
>
> он не должен себя вести, это от него ожидается
Так это проблемы ожидающего.
> я же не утверждаю, что это закон! я утверждаю, что это принято
> повсеместно,
Не принято. Примеры уже приводили.
> а тот факт что он себя так не ведет должен
> отражаться в документации
Это насилие над логикой: перечислять отсутствующие свойства.
Страницы: 1 2 3 4 вся ветка
Форум: "Прочее";
Текущий архив: 2008.01.20;
Скачать: [xml.tar.bz2];
Память: 0.64 MB
Время: 0.055 c