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

Вниз

Почему допустимо integer(<адрес в памяти>) ?   Найти похожие ветки 

 
Giemgo   (2003-04-15 15:55) [0]

Не очень силен в битовой логике. Или может даже очень не силен.

Но видел, что люди пишут, допустим, так:

integer(p)+1 когда нужен адрес байта следующего после p
где p - адрес в памяти

Хотя ведь правильней LongWord(p)+1 ?

Так как integer - это знаковое целое. А адрес не может быть отрицательным... и на хранение положительного числа у integer отводится 31 бит, в то время как адрес - это 32-ух битовое положительное число.


 
Anatoly Podgoretsky   (2003-04-15 16:04) [1]

Они расчитывают на такой факт, что в данный момент (для Д2-Д7), из размеры равны. Но для этого есть более подзодящий мезанизм, для PChar поддержана адресная математика.


 
Digitman   (2003-04-15 16:08) [2]

ну и что ?

с т.з. компилятора операция
integer(p)+1
вполне легальна - требуется сложение двух знаковых целых числа

а вот дальше, коль p - это Pointer и требуется после его модификации (любым легальным способом) обратиться к адресу в памяти, значение этого указателя рассматривается не как знаковое, а как беззнаковое целое


 
Fantasist.   (2003-04-15 17:18) [3]


> с т.з. компилятора операция
> integer(p)+1
> вполне легальна - требуется сложение двух знаковых целых
> числа


Положим, у нас есть число (8 байт):

10000011

Допустим, это адрес, а как целое число оно равно -3 (первый бит - знак). При сложении с +1 оно превращается в -2, в битовом виде 10000010, что соответствует адресу предыдущего байта, а не следующего.



 
MBo   (2003-04-15 17:25) [4]

>Fantasist
Ты ошибаешься -
однобайтовое число в дв. виде
-3 11111100
+1
-2 11111110


 
Skier   (2003-04-15 17:26) [5]

Положим, у нас есть число (8 байт):

10000011 - Это что, батенька, 8 байт ?!


 
Skier   (2003-04-15 17:33) [6]

>MBo © (15.04.03 17:25)
Борис, 11111100 - это -4 - (дополнительный код)



 
Fantasist.   (2003-04-15 17:38) [7]


> 10000011 - Это что, батенька, 8 байт


Нет, бит. Думаю, вы и сами это видите.



> Ты ошибаешься -
> однобайтовое число в дв. виде
> -3 11111100
> +1
> -2 11111110


Хорошо. Пусть так - не суть. При преобразовании к адресу все равно результат получается не адрес следующего байта.


 
Anatoly Podgoretsky   (2003-04-15 17:46) [8]

Fantasist. (15.04.03 17:18)
Вам в школу, и по количеству байт и по математическим операция и с каких пор адрес стал знаковым?

-3 11111100 +1
-2 11111101


 
Skier   (2003-04-15 17:48) [9]

>Fantasist.

> Допустим, это адрес, а как целое число оно равно -3 (первый
> бит - знак).

Если это адрес, то он воспринимаеться как беззнаковое число
см. Digitman © (15.04.03 16:08).


 
DiamondShark   (2003-04-15 17:48) [10]

У-уу! Как всё запущено.


знаковое(10) двоичное беззнаковое(10)
-3 11111111111111111111111111111101 4294967293
+1 00000000000000000000000000000001 1
-2 11111111111111111111111111111110 4294967294


Какие ещё вопросы?


 
MBo   (2003-04-15 17:52) [11]

>Skier
да, верно, ведь 11111111b=-1
да и сложил я неправильно ;)


-3 11111101
+1
-2 11111110

если рассматривать как беззнаковые
253+1=254
адрес следующего байта и есть




 
Digitman   (2003-04-15 17:57) [12]


> Fantasist


ну и что из этого следует ?

да, при расширении байта (как ShortInt) до Integer знаковый бит дублируется во все дополняемые слева разряды, и результатом сложения будет знаковый декремент

нет, при расширении байта (как Byte) до Integer знаковый бит все дополняемые слева разряды будут обнулены, и результатом сложения будет знаковый инкремент

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


 
Fantasist.   (2003-04-15 18:44) [13]

Ну вот и отличненько. А в школу, как предлагает Podgoretsky я все-таки не пойду.


> каких пор адрес стал знаковым


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


 
Giemgo   (2003-04-15 20:47) [14]

Так. Для понимания ваших ответов, которые половина неправильная, даже ответы мастеров, скажите мне такую вещь.

Если мы рассмотрим однобайтовое знаковое.

Его наибольшее значение 01111111 - это понятно.
Наименьшее значение 111111111 - в прямом коде.
Но так как числа в x86 хранятся в дополнительном, то наименьшее число будет 00000001, так как NEG 11111111=00000001

Отсюда вопрос. А как понять, что там за число хранится ? То ли
-127, то ли +1


 
default   (2003-04-15 22:27) [15]

вот ответ проще некуда
Byte(ShortInt(130) + 1) = 131
ShortInt(130) = -126
Byte(-125) = 131 (приведение к Pointer это почти то же что и к LongWord/DWORD/Cardinal)
(то есть адрес трактуется как целое беззнаковое число)
начально значение адреса: 130
конечное значение адреса: 131
вот весь фокус
а если ещё проще говорить то неважно к какому типу ты приводишь адрес
лишь бы его размер соответстовал адресу


 
Anatoly Podgoretsky   (2003-04-15 22:31) [16]

Fantasist. (15.04.03 18:44)
Сложение Integer всегда даст правильный результат, деже если к нему приведен Pointer.
В процессоре нет отдельной команды для сложения со знаком и без, на это одна единстственна команда ADD


 
Anatoly Podgoretsky   (2003-04-15 22:35) [17]

Да, в школу емеется в виду в школу Юрия Зотова, особенно первые три класса, чейчас он ведет четрверный клас. Я не помню точно в каком именно классе он объясняет операция сложени для знаковых и беззнаковых цисел. Толь первый толи второй урок. Так где речь идет про биты.


 
Giemgo   (2003-04-16 00:10) [18]

Ответьте, пожалуйста, на вопрос.

Если мы рассмотрим однобайтовое знаковое.

Его наибольшее значение 01111111 - это понятно.
Наименьшее значение 111111111 - в прямом коде.
Но так как числа в x86 хранятся в дополнительном, то наименьшее число будет 00000001, так как NEG 11111111=00000001

Отсюда вопрос. А как понять, что там за число хранится ? То ли
-127, то ли +1


 
А123   (2003-04-16 00:23) [19]

2 Giemgo (16.04.03 00:10)
11111111 это -127
00000001 это +1
А NEG тут несколько не причем, поскольку 11111111 - это уже дополнительный код.


 
А123   (2003-04-16 00:26) [20]

Пардон ступил.
11111111 - это -1
а -127 это 10000001


 
Anatoly Podgoretsky   (2003-04-16 00:49) [21]

Giemgo (16.04.03 00:10)

Наименьшее значение не 111111111 - а 10000000
NEG 11111111=00000001 -> 00000000!!! или ты про какой NEG говоришь


 
Юрий Зотов   (2003-04-16 08:14) [22]

> Giemgo

Полезные ссылки:

www.sgu.ru/kafedra/teorin/Lekciya_99.htm
www.happytown.ru/prog/data/simple.html
www.i-u.ru/biblio/arhiv/books/noname_uchInform/ec4.asp
stratum.pstu.ac.ru/~leonid/base
user.rol.ru/~voidmain/asm.zip


 
Palladin   (2003-04-16 08:27) [23]

вот ведь развели полемику из-за одного вопроса
"Почему допустимо integer(<адрес в памяти>)?"

а потому что 16 бит, они все время 16 бит, и знака у них нет, это массив бит...
а type casting"у без разницы, лишь бы размер совпадал.

по поводу вопроса

> Giemgo (16.04.03 00:10)


как понять...
как тебе надо так и понимай...
ведь ты же переменную описываешь! byte или shortint... или еще как...


 
Digitman   (2003-04-16 08:41) [24]


> Giemgo


Диапазон представлений целовых чисел со знаком, хранимых байтом
-128 .. +127, а беззнаковых целых - 0..255

Любая операция сложения/вычитания над байтом (как бы он ни интерпретировалось его содержимое - как знаковое или как беззнаковое) даст один и тот же результат - одну и ту же битовую комбинацию в результирующем байте.

Другой вопрос, что арифм.операции (например, ADD или SUB), интерпретирующие байт как знаковое целое, кроме собственно формирования результата устанавливают флаги CF (перенос/заем значащего разряда), OF (арифм.переполнение), SF (знак арифм.результата), ZF (результат равен нулю), PF (паритет результата). Любая последующая инструкция может проанализировать (либо задействовать их непосредственно) эти флаги, если это требуется по алгоритму.

Скажем, результат выполнения инструкций INC BYTE (1) и ADD BYTE,VALUE (2) будет одинаков при любом исходном содержимом операнда BYTE. Но ! Инструкция INC установит флаги ZF, SF, ОF, PF, оставив флаг CF без изменений. Инструкция же ADD установит еще и флаг CF, для того чтобы, например, следом идущая арифм.инструкция могла учесть результат выполнения предыдущей ИМЕННО как результат ЗНАКОВОЙ операции !


 
Giemgo   (2003-04-16 10:45) [25]

Слушайте, я все немного неправильно описал. Я интуитивно понимал, а объяснить не мог. Вот сейчас подумал - расскажу в чем мне кажется проблема то.

Давайте представим, что указатель - это однобайтовое целое (не хочу лишние единички и нули писать). А также integer и LongWord это однобайтовые целые.

Также предположим, что P:=01111111b

Соответственно, если мы хотим узнать номер следующего байта в памяти, делаем так:

P:=Pointer(LongWord(P)+1) правильно ? Получаем 10000000b

Но ! Если мы сделаем с помощью integer:

P:=Pointer(Integer(P)+1) что мы получим ?

Ведь 01111111b это максимальное значение для integer (напомню, что мы договорились, что integer однобайтовое знаковое). И если прибавить еденицу - то будет переполнение ! А не адрес следующего байта. Вот что я хотел сказать. Все сказанное можно отнести и к 32-ух битовым системам. По любому у integer на 1 бит меньше места для хранения числа, чем у LongWord

А теперь догадки, почему, когда используют integer нет ошибок. Да мне кажется потому, что в программах высшие области памяти не используются, особенно в программах типа Hello, World. Соответственно у существующих указателях не то, что старший бит, а вообще старший байт равен нулю. И ошибка не всплывает.


 
Anatoly Podgoretsky   (2003-04-16 10:51) [26]

Мы получим 10000000b
Книги или просто проверка в Дельфи помогут тебе встать на правильную дорго


 
Digitman   (2003-04-16 11:01) [27]


> P:=Pointer(LongWord(P)+1) правильно ? Получаем 10000000b


это не вызывает сомнений


> Но ! Если мы сделаем с помощью integer:
>
> P:=Pointer(Integer(P)+1) что мы получим ?


да тоже самое и получим ! 10000000b ! при чем здесь переполнение-то ? для последующено обращения к ячейке памяти по адресу (результирующему значению переменной-указателя P) = 10000000b никакое предыдущее "арифм.переполнение разрядной сетки" не играет никакой роли ! P^ := XXX - это же не арифм.операция !



 
Palladin   (2003-04-16 11:04) [28]

Pointer(10000000)=128
Integer(10000000)=-128;

заметь одно и тоже, а представление разное...


 
Skier   (2003-04-16 11:07) [29]

>Integer(10000000)=-128;
?!


 
Digitman   (2003-04-16 11:13) [30]


> Skier


Для простоты автор подразумевает, что Integer - это ShortInt (байт)



 
Skier   (2003-04-16 11:15) [31]

>Palladin
Мои извинения, не учёл : "напомню, что мы договорились, что integer однобайтовое знаковое"


 
Giemgo   (2003-04-16 15:05) [32]

последующено обращения к ячейке памяти по адресу (результирующему значению переменной-указателя P) = 10000000b никакое предыдущее "арифм.переполнение разрядной сетки" не играет никакой роли

Это понятно. Ну смотрите. Давайте разберем по шагам - скажите где я ошибся:

Integer(P)+1

Сначала P приводится к integer. В нашем случае это +128
И вот мне интересно в каком контексте происходит сложение. Если в контексте integer, то так получается +129, то оно в integer "не влезет". Я помню, что когда integer переходит свои границы, то в результате получается фиг знает что.
Тем более с точки зрения integer значение 10000000b это некорректный результат. Так почему он складывается нормально? Ведь если написать

i:=128
i:=i+1

- то ничего не получится


 
Digitman   (2003-04-16 15:19) [33]

10000000b
+
00000001b
-----------
10000001b

вот так физически (и никак по иному !!!) происходит сложение двух операндов в ходе исполнения процессором маш.инструкции . Хоть "со знаком" операнды, хоть "без знака" )

Это понятно ? Не вызывает вопросов ?



 
erikIvanov   (2003-04-16 15:20) [34]

Крыша у вас поешела, делать нечего биты складывать?


 
Anatoly Podgoretsky   (2003-04-16 15:25) [35]

Giemgo (16.04.03 15:05)
Число +128, как знаковое, невозможно представить в Байте!
Другое дело беззнаковое, тогда 128 + 1 = 129, неважно то ли это указаетль, трактуемый как целое, толи это чисто целое беззнаковое.

Дианазон -128 .. +127 и для беззнакового 0 .. 255


 
Digitman   (2003-04-16 15:27) [36]


> erikIvanov


вот это ты напрасно)

автор хочет разобраться детально, ЧТО и КАК происходит
разве это плохо ? это приветствовать надо !


 
evvcom   (2003-04-16 15:46) [37]

Сложение пройдет нормально.
Если будешь присваивать переменной Integer i := 127 (01111111b) + 1, то получишь 10000000b, а дальнейшее поведение программы будет зависеть от установленного флажка Overflow Checking (или директивы компилятора {$Q+} or {$Q-}). Если флаг установлен {$Q+}, то компилятор дальше сгенерит код проверки флага переполнения и если ..., то raise Exception. Если же компилируется с {$Q-}, то код сгенерен не будет и переменная примет значение -128 (10000000b)
Вроде понятно объяснил...

Попутно вопрос к Мастерам, например, Digitman: а как Вы получили такую медаль с надписью Мастер DELPHI? Или Вы просто являетесь создателями сего славного проекта? Или же ее все же можно заработать?
Как поется у Высоцкого: "Я, Вань, такую же хочу!"


 
Digitman   (2003-04-16 16:25) [38]

>evvcom

по поводу опций компилятора - пока о них речь не идет.

по поводу "надписи" :


> являетесь создателями сего славного проекта

нет, не являюсь


> как Вы получили такую медаль

"У меня секретов нет, слушайте, детишки !"
Просто я сподобился года 2-3 тому назад более точно процитировать Владимира Семеныча, в оригинале поющего не "ЖЕ хочу" , а "ЖУ хочу"... За что и был удостоен Фондом ув. Владимира Семеныча столь высокой награды !!) .. А собственно к Делфи оная отношения не имеет)


> ее все же можно заработать?


Безусловно !! ТОлько зачем ее "зарабатывать"-то ?? Вот еще !! Пыхтеть-то)...
Все ж гораздо тривиальней : заявки на получение сей замечательной "фенечки" подаются в "Потрепаться", там же практически без бюрократических проволочек и происходит публичная церемония "награждения")) ... Хочешь ? Имей !)... Не досталось ? Забирай мою и носи не стаптывай !) Мне не жалко))


 
evvcom   (2003-04-16 16:33) [39]

>> по поводу опций компилятора
это я для того, чтобы человеку понятно было откуда появляются "ошибки" (если вообще появляются).
А так можно складывать все, что угодно, байты они и есть байты. Главное, правильно преподнести это компилятору, чтобы не ругался, где не следует. Т.е., если я правильно понимаю задачу, то я правильно делаю преобразования типов, и компилятор это с удовольствием проглатывает.


 
Anatoly Podgoretsky   (2003-04-16 16:41) [40]

А что бы от такого не зависить, раз уж мы условилиль, что у нас это является указателем, то надо использовать BYTE.
И в реальной жизни, вместо Integer - LongWord/Cardinal


 
Giemgo   (2003-04-16 18:31) [41]

1) Опять вы меня не допоняли... ;(

10000000b
+
00000001b
-----------
10000001b

вот так физически (и никак по иному !!!) происходит сложение двух операндов в ходе исполнения процессором маш.инструкции . Хоть "со знаком" операнды, хоть "без знака" )

Это понятно ? Не вызывает вопросов ?


Это-то вопросов не вызывает. А вот вызывает вопросы такое:

01111111b
+
00000001b

Ну как такое для shortint может пройти ? Получается что 127+1=-128 ахинея какая-то

2) Вот тут подумалось. А что, если сложить (-1)+(-1)

11111111b
+
11111111b
---------

должно получится (-2), то есть:

11111110b Но по логике получается:
111111110b


 
Anatoly Podgoretsky   (2003-04-16 18:46) [42]

Не надо считать адреса числами, тем более со знаком!

1. Ахинея точно, но только у тебя, указатель это не число
127+1=128 (адрес со смещением 128)

2. Переполнение адресной сетки
254+254=508 при размере адресной сетки 255


 
Serginio   (2003-04-16 19:22) [43]

Мне конечно нравится ваша полемика. Может конечно ошибаться, но
вторая полвина адресов 4ГБ пространства отдана для системных адресов виндов.Так что по барабану. А если учесть 64 разрядные процессоры то LongWord не правильно а Integer правильно, так как становится Int64.


 
Anatoly Podgoretsky   (2003-04-16 21:01) [44]

Serginio (16.04.03 19:22)
В истории существования процессоров Интел, не всегда ширина адреса совпадала с разрядной сеткой просцессора.
Если посмотреть

8080 8 бит 16 бит
8086-286 16 бит 20 бит
+386 16/32 20/32


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

Это примерно так как многие погорели при переходе с 16 битной среды на 32 битную, считая, что Integer равен 16 битам
Да и Pointer менялся с 16/32 бит на 32 бита.
Все это опачные трюки Integer(P), особенно что есть специальный тип, PChar для которого поддержана адресная математика P := P + I


 
Giemgo   (2003-04-16 23:07) [45]

Ахинея точно, но только у тебя, указатель это не число
127+1=128 (адрес со смещением 128)


Блин. Указатель - это не число, ну и чего ?!

(Integer(P)+1 тут то будут СКЛАДЫВАТЬСЯ ЧИСЛА.

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

УРА ! Аллилуя ! Разобрался. За что спасибо evvcom © (16.04.03 15:46)

Все таки оказалось по моему.
p:=Pointer(Integer(P)+1) это не корректно. Нужно применять LongWord.

Для демонстрации ошибки можно применить такой код.

procedure TForm1.Button1Click(Sender: TObject);
var P:Pointer;
begin
p:=Pointer($7FFFFFFF);
p:=Pointer(Integer(P)+1):
// Какой-то код
end;

Ведь может быть такой адрес в памяти, как $7FFFFFFF ? Может, конечно ! А если я хочу узнать адрес следующего байта памяти ?
Хоть тут и говорили, что использование integer"а не несет угрозы, но ведь несет !
Если я как показано выше сделаю и у меня установлен флажок в опциях проекта Overflow checking, то вылезет exeption ! И соответственно последующий код НЕ выполнится ! А если использовать LongWord все ок !

Конечно, по умолчанию этот флажок Overflow checking не стоит. И как я уже отмечал обращения к таким адресам памяти как $7FFFFFFF маловероятны, но существование проблемы налицо !!!

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


P.S. Уже не в тему, но коли мы затронули побитовые операции.

Не понимаю как складываются отрицательные числа.
Допустим: (-1)+(-1)

11111111
+
11111111
----------
?

По идее, -2 получится. Но если побитово складывать, получится переполнение... странно...


 
default   (2003-04-16 23:31) [46]

procedure TForm1.Button1Click(Sender: TObject);
var
P: Pointer;
begin

P := Pointer($7FFFFFFF); // начальный адрес: $7FFFFFFF
Caption := IntToStr(LongWord(P));
P := Pointer(Integer(P) + 1); // конечный адрес $8FFFFFFF
Caption := Caption + " : " + IntToStr(LongWord(P));

end;


нифига ты непонял
смотри код выше
скажи ты всегда всё догоняешь(типа) с 20 раза да ещё и не верно?


 
default   (2003-04-16 23:39) [47]

procedure TForm1.Button1Click(Sender: TObject);
var
i: LongWord;
P: Pointer;
begin

Caption := "Ты не прав";
for i := 0 to $FFFFFFFF do begin
P := Pointer(i);
if Pointer(Integer(P) + 1) <> Pointer(LongWord(P) + 1) then begin
Caption := "Я не прав";
Break;
end;
end;

end;

если ты уж до такой степени твердолобый этот код УБЕДИТ тебя что ты НЕ ПРАВ!


 
Giemgo   (2003-04-16 23:57) [48]

default, ха ха. А ты мой пост Giemgo (16.04.03 23:07) читал ? Если читал - то мне тебя очень жаль


 
default   (2003-04-17 01:58) [49]

Giemgo
и что ?
мне кажется ты тупишь с переполнением
завтра лично проверю
но это значения не имеет никакого смотри (16.04.03 23:39)


 
default   (2003-04-17 02:21) [50]

procedure TForm1.Button1Click(Sender: TObject);
var
P1, P2: Pointer;
begin

Integer(P1) := Integer(3000000000);
LongWord(P2) := LongWord(3000000000);
if P1 = P2 then ShowMessage("Ну ты дурак редкий! P.S. Достал просто.")

end;


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


 
А123   (2003-04-17 04:40) [51]

2Giemgo (16.04.03 23:07)

>Не понимаю как складываются отрицательные числа.
>Допустим: (-1)+(-1)

>11111111
>+
>11111111
----------
>?

>По идее, -2 получится. Но если побитово складывать, получится >переполнение... странно...

У тебя слишком "боязненное" отношение к переполнению. Переполнение - не есть ошибка, в каком либо виде. Это лишь приводит к установке флагов процессора, как уже указал Digitman. А вот учитывать (или не учитывать) эти флаги в последующих инструкциях - это задача или компилятора (если программа на Дельфи) или твоя (если пишешь на ассемблере).


 
Sha   (2003-04-17 09:07) [52]

Как уже писал Anatoly Podgoretsky © (15.04.03 22:31)
для сложения целых чисел размером до 32 бит в процессоре используется одна единстственная команда ADD.
При сложениии одинаковых битов будет получен одинаковый (в битовом выражении) результат.
А как этот результат потом интерпретировать (integer, cardinal) - не имеет значения. Все равно при обратном кастинге типа вы получите тот же самое значение (т.к. битовое выражение не изменилось).



 
Palladin   (2003-04-17 09:41) [53]

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


 
Anatoly Podgoretsky   (2003-04-17 09:44) [54]

Так Юрий Зотов специально организовал уроки для начинающем на этом сайте, где данный вопрос представления чисел в процессорах и выполнения операций над ним также рассмотрен.


 
Giemgo   (2003-04-17 12:37) [55]

default © (17.04.03 02:21)

Ну ты даааааал. Если сам не понимаешь о чем я тут говорю - так и не лезь. Разберись, пожалуйста, САМ. Как разобрался я. А потом советуй.

for i := 0 to $FFFFFFFF

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

Если ты хочешь все таки разобраться как и я, ОТВЕТЬ НА ВОПРОС:

procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
p:Pointer;
begin
{$Q-}
Caption := "Ты не прав";
i:=$7FFFFFFF;
P:=Pointer(integer(i)+1);
if P<>nil then Caption:="Я не прав";
{$Q+}
end;

Внимательно проанализируй каждую строчку кода и подумай. А почему это в конце операции форма имеет заголовок "Ты не прав" ?

Внимание ! Вопрос только для default. Пусть он напишет ответ.

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

А у меня ко всем остальным вопрос:

-1 это 11111111b ?
А 11111111b это $FF

Тогда почему не работает:

var i:shortint;
...
i:=$FF

?


 
Palladin   (2003-04-17 12:46) [56]


> Тогда почему не работает:

потому что это проверка на дурака на уровне компилятора...
i:=shortint($ff) или
byte(i):=$ff;

этим ты закроешь глаза компилятору...


 
Palladin   (2003-04-17 12:52) [57]

тьфу :)
защита от дурака всмысле

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


 
default   (2003-04-17 17:06) [58]

Удалено модератором
Примечание: Воздерживайся от личных оскрблений


 
Sandman25   (2003-04-17 18:27) [59]

"for i := 0 to $FFFFFFFF do" приводит не к бесконечному циклу, а наоборот, к невыполняемому ни разу (поэтому компилятор и удаляет цикл). Для захода в цикл нужно писать "for i := $FFFFFFFF to 0 do". Без шуток.


 
Anatoly Podgoretsky   (2003-04-17 18:39) [60]

Это зависит от типа i
Integer, выполнится два раза
Int64, Cardinal (начиная с версии 3 или выше, до этого диапазон был в два раза меньше), выполнится 2^32 раз


 
default   (2003-04-17 18:48) [61]

procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
p:Pointer;
begin
{$Q-}
Caption := "Ты не прав";
i:=$7FFFFFFF;
P:=Pointer(integer(i)+LongWord(1));
if P<>nil then Caption:="Я не прав";
{$Q+}
end;
пиши так если боишься за переполнение которое очень
маловероятно
предыдущее сообщение было удалено поэтому лень повторяться
что было то было



 
Anatoly Podgoretsky   (2003-04-17 18:53) [62]

Приношу прощение только сейчас заметил, для Integer 0 раз, поскольку от 0 до -1, в голове местами операнды поменял :-(


 
Giemgo   (2003-04-17 19:10) [63]

default, не знаю, что ты там мне написал, но ты не сердись. Я тебя обидеть не хотел, просто указал, что тебе нелишне будет самому поразбираться в теме или повнимательнее почитать мои посты.

если ты уж до такой степени твердолобый этот код УБЕДИТ тебя что ты НЕ ПРАВ!

Слушай, твои наезды просто беспочвенны. Данный тобой код меня ни в чем не убедит, так как он полностью неправильный. И вообще, если бы даже цикл был составлен правильно, что из этого ? Я не говорил, что условие "Pointer(Integer(P) + 1) <> Pointer(LongWord(P)" когда-нибудь выполнится. Я говорил про переполнение.

В своем посте Giemgo (17.04.03 12:37) я задал тебе вопрос, ответь на него, пожалуйста, даже если ответ тебе очевиден


Anatoly Podgoretsky © (17.04.03 18:39)
Это зависит от типа i
Integer, выполнится два раза
Int64, Cardinal (начиная с версии 3 или выше, до этого диапазон был в два раза меньше), выполнится 2^32 раз


Анатолий, а это вы про что ?


 
Palladin   (2003-04-17 19:43) [64]

про то что если i:integer, то цикл выполнится 2 раза....
если i:int64 или i:cardinal, то цикл выполнится 4294967296 раз


 
default   (2003-04-17 20:13) [65]

я уже говорил про переполнение
i := $7FFFFFFF
в Pointer(integer(i)+1); // получается что MaxInt + 1 > MaxInt
если тебе этого так хотелось
чтобы его никогда не было
Pointer(integer(i)+LongWord(1));
or
Pointer(LongWord(i)+1);
но этот момент почти никакого отношения не имеет к первоначальному вопросу в нём другая фишка была
про которую писал Sha и многие другие...



 
Anatoly Podgoretsky   (2003-04-17 20:35) [66]

Giemgo (17.04.03 19:10)
Anatoly Podgoretsky © (17.04.03 18:39)
Это зависит от типа i
Integer, выполнится два раза

Palladin © (17.04.03 19:43)

Я уже поправился - 0 раз
Остальное правильно.


 
Giemgo   (2003-04-17 20:45) [67]

Повторю мой вопрос: складываем два однобайтовых числа отрицательных.

11111111b
+
11111111b
---------
?

Должно получится -2. Но если складывать побитово столбиком, то, по идее, возникнет переполнение !
Так почему здесь компилятор не сообщает о переполнении ?

Если написать

var i:shortint;
...
i:=127;
i:=i+1

то компилятор выдаст Integer Overflow, так как переполнение.

Ну а ведь как я показывал выше (-1)+(-1) тоже переполнение дает! Но компилятор уже не сообщает почему то.


 
Palladin   (2003-04-17 20:54) [68]

хм я тоже ошипся... :)
2 раза выполнится
for i:=integer($ffffffff) to 0
в общем это уже оффтопик пошол...


> Giemgo (17.04.03 19:10)

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


 
Anatoly Podgoretsky   (2003-04-17 20:54) [69]

-1 + -1 равно двум, никакого переолнения нет. Идея не верная.
127 + 1 равно 128, вот сдесь переполнение.


 
Anatoly Podgoretsky   (2003-04-17 20:55) [70]

-2 конечно


 
Giemgo   (2003-04-17 20:59) [71]

но этот момент почти никакого отношения не имеет к первоначальному вопросу в нём другая фишка была

Ух ты ! Вот блин. А о чем, по твоему, был вопрос ?! Мне это очень интересно узнать ! По моему, ты так увлекся доказательством мне чего-то посредством невыполняющихся циклов, что ушел от сути. Первоночальный вопрос читал ? Перечитай !
Собственно говоря, он о том и был. Могу процитировать, чтобы ты не скролил:

Но видел, что люди пишут, допустим, так:

integer(p)+1
...
Хотя ведь правильней LongWord(p)+1 ?


Да ? Так оно и есть ? Правильней писать LongWord ! По моему, это именно то, что ты и написал:

Pointer(integer(i)+LongWord(1));
or
Pointer(LongWord(i)+1);
пиши так если боишься за переполнение которое очень
маловероятно


Да, маловероятно, я и об этом писал. Но проблема есть. ВОТ И ВСЕ, ЧТО Я ХОТЕЛ СКАЗАТЬ.

P.S. Ты, конечно, будешь говорить, что это очевидно и и т.д. Только вот уверен, что если бы был тест при приеме на работу "Чем опасен p:=Pointer(Integer(p)+1)" ты бы не ответил. Как и я.

Потому что даже мастера тут не сразу въехали. Не говоря уж о том, что некоторые и считают неправильно :))))


 
Anatoly Podgoretsky   (2003-04-17 21:08) [72]

Правильнее PChar + 1


 
Palladin   (2003-04-17 21:13) [73]

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

ЗЫ LongWord(i)+1 тоже будет переполнение при i=$ffffffff


 
default   (2003-04-17 22:18) [74]

тема уже исчерпана фиг знает сколько времени назад
Giemgo случайно заметив переполние стал "кричать" что он был прав и тд и тп
хотя начиная тему явно об этом и не догадывался
но это такой пустяк блин даже говорить о нём не хочется...
надо же так развести(это относится к Giemg-е)это надо ещё уметь зы
что меня в тебе поражает так это то что ты не изучив двоичную арифметику говоришь что
что-то там не так...странно...ууууу ааааа ха ха ха
всё через Ж делаешь
тебе же Юрий Зотов дал ссылки...ну ты видно полезную информацию игноришь пожизни
отсюда и столько вопросов!
и ещё не сочти за оскорбление но 90% твоих слов "глаголят" такую ахинею что уши вянут
серьёзно
я думаю любой подтвердит
стремление к знаниям видно но какое-то оно кривое у тебя...или мышление кривое...
вроде догоняешь но с 10-ого раза
и возвращаясь к переполнению
я до этого не знал(или забыл) что если пишешь типа Integer(1000) + 1 - компилятор
требует чтоб рез-ат этого выражения был Integer - поэтому об этом и не задумывался


 
Giemgo   (2003-04-17 23:42) [75]

ЗЫ LongWord(i)+1 тоже будет переполнение при i=$ffffffff

Это понятно. Только вот указатель тоже не может быть больше $FFFFFFFF. Так что это уж точно не проблема. А если будет переход на новую платформу - то это совсем другой разговор.

а вот ты так и не допер... тебя жаль...

Я, конечно, ламер по сравнению с тобой. Но, по моему, это ты не допер. Мне кажется на примере я ясно показал, что Integer и LongWord это не абсолютно одинаковое.
Если в одном случае возникает исключение, а в другом не возникает - это можно считать разницей, ты как считаешь то ?!

Giemgo случайно заметив переполние стал "кричать

Абсолютно не согласен. Переполнение я искал специально. Просто сразу не сообразил как сформулировать проблему. Да и после того как сформулировал меня недопонимают.

тебе же Юрий Зотов дал ссылки

Я их прочитал между прочим. И собственно говоря по их прочтении у меня и возникло подозрение насчет корректности integer(p)+1
---------------------------

Ну народ. Я вам удивляюсь. Вроде я достаточно четко объяснил, что в случает integer возникает переполнение. В случае LongWord переполнения не возникает. Я ОСОЗНАЮ, что и там и там хранятся одинаковые байты. Но из-за установки флага переполнения Дельфи при соответствующих установках компилятора генерит exeption, который может кардинально поменять результат. Я прав. Это очевидно.
-----------------------------------------------

У меня остался вопрос.

-1 + -1 равно минус двум, никакого переолнения нет. Идея не верная.
127 + 1 равно 128, вот сдесь переполнение.


То есть, как понимаю, в первом случае устанавливается флаг переноса на который Дельфи не реагирует исключением. А во втором случает устанавливается флаг переполнения на которое дельфи как раз реагирует исключением ?
Если это так - просто скажите да.

P.S. Хоть я и не понимаю недоброжелательное отношение многих к моим искренним попыткам разобраться с этой кухней и не понимаю чем я так насолил, что люди ругаются на меня. Но в любом случае прошу прощения за доставленные неудобства


 
Palladin   (2003-04-18 00:00) [76]

дык вот в чем соль то...

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

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

просто маленькое уточнение, про прием на работу
p:=Pointer(Integer(p)+1) абсолютно безопасен при {Q-}


 
Anatoly Podgoretsky   (2003-04-18 00:26) [77]

Есть несколько флагов в процсессоре

OV устанавливается если происходит неверная смена знака для знакоых целыч, 128 на самом деле равно -128, что неверно. Это будет переполнение для знаковых

CY - если есть перенос из старшего разряды, это будет переполнение для беззнаковых.

S - флаг знака.

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

Флаг переноса <> флагу переполнения, а ты их путаешь.

Прм сложении -1/255 (FF) с +1 (01) будет установне CY, результат 0, ошибка для беззнаковых (или перенос в следующий разряд, нормально для знаковых)
1111 1111
0000 0001
1.0000 0000

Прм сложении -1/255 (FF) с -1 (FF) будeт установлены CY, S, результат -2/254 (FE), ошибка для беззнаковых (или перенос в следующий разряд, нормально для знаковых)
1111 1111
1111 1111
1.1111 1110

Прм сложении +127 (7F) с +1 (01) будeт установлены OV, S, результат -128/128 (FE), ошибка для беззнаковых (переноса нет, нормально для знаковых)
0111 1111
0000 0001
0.1000 0000

Прм сложении -128/128 (80) с -1/255 (FF) будeт установлены CY, OV, результат 0, ошибка для беззнаковых (есть перенос, ошибка для обеих)
1000 0000
1000 0000
1.0000 0000


 
Giemgo   (2003-04-18 00:43) [78]

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

Не иронизируй. Если ты вдумаешься, то знание галочек компилятора это не фигня. Из-за них ты можешь долго искать ошибку, как искал я в другой своей ветке. Если ты целый день будешь искать ошибку - а она заключается в одной галке, ты будешь выглядить глупо, согласись ?
Можно также утверждать, что при приеме на работу проверяют, знаешь ли ты что Delphi объекто-ориентированный язык. Конечно, нет. Но если узнают, что ты этого не знаешь... сам понимаешь

ладно, цель достигнута, твою мысль я понял

скажи честно - ты ее только сейчас понял ? Я не про то, что ты тупой. Я про то, что может я объяснять не умею, потмоу как повторял неоднократно.

а ты, в свою очередь, понял что ложки нет

Да, конечно. Если честно, то я с первого твоего поста понял, что ложки нету. И даже открою секрет, догадывался о ее несуществовании :)))

просто маленькое уточнение

А вот тут я не очень понимаю. В спраке то написано как ты сказал.

И на самом деле такой код вызывает исключение:

{$Q+}
i:=$7FFFFFFF;
i:=i+1;

Но вот почему следующий код вызывает исключение ?

{$Q-}
i:=$7FFFFFFF;
i:=i+1;
{$Q+}


 
Palladin   (2003-04-18 00:59) [79]


> Giemgo (18.04.03 00:43)

цель достигнута первоначальная...
тебе в стало понятно почему же допустимо integer(<адрес в памяти>)
а вопрос "к каким подводным камням это может привести?" очень долго у тебя формировался, пока наконец не оформился на 70какомто посте...
давай не будем рассуждать больше, а просто ты научишься обдумывать вопрос...


 
Palladin   (2003-04-18 01:03) [80]


> Но вот почему следующий код вызывает исключение ?
>
> {$Q-}
> i:=$7FFFFFFF;
> i:=i+1;
> {$Q+}


вот такой код не вызовет исключений при любом Q
проверено

i:=$7fffffff;
p:=pointer(integer(i)+1);


 
Giemgo   (2003-04-18 20:34) [81]

вот такой код не вызовет исключений при любом Q
проверено

i:=$7fffffff;
p:=pointer(integer(i)+1);


ТЫ ПЕРЕГРЕЛСЯ ЧТО ЛИ ? Все таки это ТЫ не догоняешь, судя по всему. Уж разбирись, пожалуйста сам. А то на меня наезжал, наезжал...


 
Palladin   (2003-04-18 22:31) [82]

нет не перегрелся...
не выспался...


 
Giemgo   (2003-04-19 11:44) [83]

Люди, остался непонятным один вопрос!

По идее {$Q+} говорит компилятору, что должен быть сгенерирован код проверки переполнения. Но пчему при таком коде вылезает переполнение:

{$Q-}
i:=$7FFFFFFF;
i:=i+1;
{$Q+}

Почему ?! Ведь сначала стоит {$Q-} ! Причем, если нижний {$Q+} убрать, то все ок...

СТРАННО !

P.S. А у вас тоже так ? Может такой глюк у моей дельфи ?


 
Giemgo   (2003-04-19 17:23) [84]

Неужели никто не просветит меня ?

Или я всем надоел ? Могу ник сменить


 
Giemgo   (2003-04-19 23:05) [85]

Удалено модератором
Примечание: Еще один ап и будет даун


 
Giemgo   (2003-04-20 12:58) [86]

Удалено модератором


 
Giemgo   (2003-04-21 22:44) [87]

Ну я наверное плохо объясняю...

{$Q+} по идее включает проверку переполнения. {$Q-} выключает.
Но почему то Exeption выскакивает в таком коде

{$Q-}
i:=$7FFFFFFF;
i:=i+1;
{$Q+}

А ведь тут сначала идет {$Q-}, а потом {$Q+}


 
Giemgo   (2003-04-23 21:29) [88]

Мастера, ну уделите внимание то !


 
jack128   (2003-04-23 21:36) [89]

$O + F1
RTFM


 
Giemgo   (2003-04-24 23:31) [90]

jack128, а это здесь при чем ? Оптимизация выключена. Ты бы повнимательнее на вопрос посмотрел !

Дело в том, что код ДОЛЖЕН выдавать исключение, когда идет директива {$Q+} !!! ПЛЮС !

А он выдает исключение ТАКЖЕ если идет сначала минус, а потом плюс !!!

{$Q-}
i:=$7FFFFFFF;
i:=i+1;
{$Q+}


 
jack128   (2003-04-24 23:57) [91]


> {$Q+} по идее включает проверку переполнения. {$Q-} выключает.
Каким образом вкл/выкл оптимицации должно вкл/выкл проверки переполнения??


 
MBo   (2003-04-25 00:09) [92]

Если бы ты не был так по-идиотски настырен, то тебе давно бы уже ответили, что многие опции действуют на процедуру или функцию в целом - стековый фрейм должен быть единообразен.
Если в процедуре есть {$Q+}, вся она компилируется с проверками.
Это можно увидеть в ассемблерном коде.
Читай книжки, и сам разбирайся.


 
Anatoly Podgorestky   (2003-04-25 00:14) [93]

И я про то же, давно болт заложили :-)


 
Giemgo   (2003-04-25 19:41) [94]

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

Спасибо большое за ответ. У меня опять маленький вопросик. Такой код не вызывает исключения:

{$Q+}
i:=$7FFFFFFF;
i:=i+1;
{$Q-}

То есть, для компилятора определяющей считается директива идущая последней, верно ?


И я про то же, давно болт заложили :-)

обидно читать


 
Anatoly Podgoretsky   (2003-04-25 19:44) [95]

Но ведь правда, к дисскуссии больше ни кто не подключается.



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

Форум: "Основная";
Текущий архив: 2003.05.08;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.74 MB
Время: 0.01 c
14-23396
Evg12
2003-04-20 00:17
2003.05.08
Интересует нормальный компрессор (паковщик)


1-23065
Intell
2003-04-25 10:07
2003.05.08
Компонент или прога для вытягивания *.swf из EXE.


1-23195
Andrey Filatow
2003-04-24 08:53
2003.05.08
Эффекты


14-23329
race1
2003-04-18 12:59
2003.05.08
ностальжи


3-23027
AleksandrKu
2003-04-18 12:49
2003.05.08
Количество записей в Select?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский