Часть полного текста документа:Семь чудес и два фокуса на Дельфи Максим Кузьминский Верите ли Вы в чудеса или нет, Вы наверняка согласитесь со мной, что иногда что-то такое случается с кодом наших программ, и они вдруг перестают компилироваться или, что еще коварнее, начинают выдавать совершенно непредсказуемый результат. И вот тогда, сознайтесь, вас начинают посещать странные мысли об участии во всех этих чудесах неких потусторонних сил. В этой статье мы попытаемся сдернуть таинственный покров с нескольких, самых простых "чудес" и убедимся, что все это - только обман, иллюзия, а зачастую - искусное мошенничество. Мы рассмотрим семь (из многих) таких чудес и попробуем разгадать их секреты. Поняв механизм их происхождения, мы, в заключении, покажем два примера использования этих тайных сил в "мирных целях". Наша цель - лучше узнать Delphi и в будущем избежать некоторых труднообъяснимых ошибок. Для того, что бы вы поняли, что я имею в виду, давайте рассмотрим один очень простой пример. Чудо Первое (Round Miracle). Откройте Delphi, создайте новый проект, назовите его AllMiracles, положите кнопку на главную форму и напишите в обработчике события OnClick следующий код: procedure TfrmAllMiracles.btnRoundMrclClick(Sender: TObject); begin ShowMessage( IntToStr( Round(3.5) - Round(2.5) ) ); end; Figure 1. А теперь остановитесь и скажите, какой результат вы ожидаете увидеть. Я надеюсь вы не сказали "1", ведь иначе это не было бы чудо. Те, у кого хорошо развита интуиция, могут сказать "0", и это будет еще дальше от правильного ответа. И только те, кто часто играет в Спортлото или, на худой конец, внимательно читает документацию, ответит "2" и это будет правильно. Не верите? - жмите F9. Читаем Help по функции Round: Round returns an Int64 value that is the value of X rounded to the nearest whole number. If X is exactly halfway between two whole numbers, the result is always the even number. Вот такое оно, "Круглое чудо". Надеюсь, теперь вы поняли, о чем мы будем говорить сегодня. В этой статье нет сложных, замысловатых примеров. Код - предельно упрощен что бы выделить саму суть проблемы. А наше с вами дело - разобраться в ней и, если можно, исправить ситуацию. Как, например, в следующем случае. Чудо Второе (Absolute Miracle). Положите на главную форму созданного ранее проекта новую кнопку и напишите в его обработчике события OnClick такой код: procedure TfrmAllMiracles.btnAbsMrclClick (Sender: TObject); var i1: int64; begin i1:= abs(low(integer)); ShowMessage(IntToStr(i1)); end; Figure 2. Прежде чем нажать F9, проанализируем написаное. Low от integer - значение известное всем, записанное даже в Help'е и равное -2147483648, т.е. число отрицательное. Help не говорит о функции Abs ничего нового: Abs returns the absolute value of the argument X. X is an integer-type or real-type expression. Переменная i1 описана как int64, и это правильно, потому что 2147483648 - уже выходит за границы типа integer. Это значение (2147483648) мы и ожидаем увидеть на экране, не так ли? А вот и нет. Проверьте. На экране вновь - 2147483648. Как абсолютное значение может быть отрицательным? Давайте еще раз, повнимательнее рассмотрим выражение abs(low(integer)). Что можно еще сказать про него? Не смотря на наличее в нем функций, это - константа Читаем Help по теме "Constant expressions": ...Constant expressions cannot include variables, pointers, or function calls, except calls to the following predefined functions: Abs...Low... попробуем описать константу со значением равным этому выражению: ... const ci = abs(low(integer)); ... Figure 3. Код компилируется. ............ |