Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.07.25;
Скачать: CL | DM;

Вниз

Почему так?   Найти похожие ветки 

 
SergP ©   (2004-07-08 23:54) [0]

Почему эти два куска кода работают по разному?

function proverka1(a:byte):boolean;
begin
a:=a-30;
result:=a<5;
end;

function proverka2(a:byte):boolean;
begin
result:=(a-30)<5;
end;


 
Palladin ©   (2004-07-08 23:58) [1]

Это в каком смысле они по разному работают?


 
SergP ©   (2004-07-08 23:59) [2]

Код который генерит компилятор я не смотрел. Лень...
Но интерестно как он считает:
result:=(a-30)<5  ?

Преобразовывает это в
result:=a<35 или при вычислении a-30 использует результат не типа byte ?


 
DeadMeat ©   (2004-07-09 00:00) [3]


> result:=a<35 или при вычислении a-30 использует результат
> не типа byte ?

Скорее всего...

---
...Death Is Only The Begining...


 
SergP ©   (2004-07-09 00:00) [4]


>  [1] Palladin ©   (08.07.04 23:58)
> Это в каком смысле они по разному работают?


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


 
YurikGL ©   (2004-07-09 00:02) [5]


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

Видимо, при а<30 ?


 
Palladin ©   (2004-07-09 00:06) [6]

я не поленился...
В первом варианте от значения находящегося в стеке отнимается 30 и потом это значение сравнивается... используется сравнение с al
Во втором варианте все приводится к 32 и идет обработка eax...
почему? вопрос к borland...


 
SergP ©   (2004-07-09 00:09) [7]


> Видимо, при а<30 ?


Ага...


 
YurikGL ©   (2004-07-09 00:10) [8]


> SergP ©   (09.07.04 00:09) [7]

Могу попробовать объяснить по простому, в первом случае результат приводится к byte, во втором, - к longint или чему-то подобному.


 
Palladin ©   (2004-07-09 00:11) [9]

А конкретный пример разного результата можно привести?


 
DeadMeat ©   (2004-07-09 00:12) [10]

Если а будет меньше 30... т.е. 29, 28, 27, 26... Кажись так...

---
...Death Is Only The Begining...


 
Anatoly Podgoretsky ©   (2004-07-09 00:14) [11]

Так нельзя использовать, байт это беззнаковое, а при -30 может произойти переполнение.


 
SergP ©   (2004-07-09 00:17) [12]


>  [9] Palladin ©   (09.07.04 00:11)
> А конкретный пример разного результата можно привести?


при a>=35
proverka1=false
proverka2=false

при 30<=a<35
proverka1=true
proverka2=true

При a<30 имеем разные результаты:
proverka1=false
proverka2=true


 
jack128 ©   (2004-07-09 00:17) [13]


> Так нельзя использовать, байт это беззнаковое, а при -30
> может произойти переполнение
оно и при +30 может произойти ;-)


 
Palladin ©   (2004-07-09 00:23) [14]

это очень поучительно, когда работа в стеке идет с одним байтом и когда проводится реальное сравнение... работа с параметр в первом случае как я уже сказал ведется как с байтом (al), соответсвенно 10-30=235 что естественно больше чем 30... во втором случае все справедливо переводится в знаковое integer и сравнение происходит корректно...


 
jack128 ©   (2004-07-09 00:30) [15]


> это очень поучительно,
угу. C {$R+} и {$Q+} - навсегда -)


 
Piter ©   (2004-07-09 00:46) [16]

ну тут уже ответили, но вставлю свои пять копеек...

Это потому что вычисления проводятся как integer, а потом идет приведение типов.

a:=a-30;
result:=a<5;


Допустим, параметр "a=20".
В этом случае "a-30" будет "-10".
Потом идет приведение типов, "-10" приводится к типу Byte (к левой части). В этом случае получается, что "a=246". Ибо "-10", а точнее $F6 в понимании Byte это 246.
А 246 никак не меньше пяти. Значит, будет False.
Правда, при приведении "-10" к Byte будет сгенерировано исключение ERangeError, если включить галочку "Project->Options...->Compiler->Range Checking"

----------------------------------------------------------------------------------------------------

function proverka2(a:byte):boolean;
begin
result:=(a-30)<5;
end;


в этом случае вычисления проводятся тоже как integer. Если "a=20", то "a-30" получается "-10". И далее не идет никакого приведения к Byte, поэтому "-10" сравнивается с "5". Конечно, 5 больше. Поэтому True.
Вот и все различия.
Только заметь, что при включенном "Range Checking" первый вариант будет выдывать исключение, а второй нет. То есть, первый вариант работает "неправильно".
Поэтому отлаживать проект надо при включенных "Range Checking" и "Overflow Checking". А в конечном билде их отключать.

Можно еще вычитать не 30, а допустим 2147483678:

function proverka1(a:byte):boolean;
begin
a:=a-2147483678;
result:=a<5;
end;

function proverka2(a:byte):boolean;
begin
result:=(a-2147483678)<5;
end;


Тогда если даже "a=20" то обе функции будут все равно выдавать False (если отключить проверки на Range и Overflow).

Ибо тогда во втором случае уже будет переполнен integer.
И в понятии integer "20 - 2147483678" будет равно "2147483638" как это не парадоксально :)

А вообще http://www.baseprogram.narod.ru


 
Anatoly Podgoretsky ©   (2004-07-09 01:26) [17]

jack128 ©   (09.07.04 00:17) [13]
Да но у него отключены все проверки и при варианте 1 результат обрезается по модулю 256, а во втором случае нет.



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

Текущий архив: 2004.07.25;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.023 c
4-1082826122
OSokin
2004-04-24 21:02
2004.07.25
JournalRecord


14-1088935805
Rouse_
2004-07-04 14:10
2004.07.25
С Днем Рождения 4 июля


4-1086776514
Dmitry
2004-06-09 14:21
2004.07.25
запуск двух копий программы


1-1089639089
Death_R
2004-07-12 17:31
2004.07.25
Запись масcива в TVarRec


14-1089242699
Sanek_metaller
2004-07-08 03:24
2004.07.25
Thumbs.db