?

Log in

No account? Create an account
 
 
24 January 2013 @ 04:43 pm
Did you know?  
Вы тоже раньше думали, что функция abs() возвращает всегда неотрицательные значения?

=============

#include <stdio.h>
#include <stdlib.h>

main()
{
int a = (int)0x80000000;
int b1 = abs(a);
int b2 = abs(a+1);
printf("%d %d\n", b1, b2);
}

=============

$ gcc 1.c
$ ./a.exe
-2147483648 2147483647

=============
 
 
 
capt_threepwood: Guybrush Threepwoodcapt_threepwood on January 24th, 2013 01:04 pm (UTC)
ага, а ещё при добавлении единицы к положительному числу модуль уменьшается )
Nick Gavrikov: pic#74705469nickgavr on January 25th, 2013 04:01 am (UTC)
Ну это если переполнение - известная штука. А вот с abs() лично для меня это было новостью :)
Денис: pic#118878298mithraen on January 24th, 2013 02:26 pm (UTC)
Вот за что я ненавижу все эти макроассемблеры :)
Nick Gavrikov: pic#74705469nickgavr on January 25th, 2013 04:00 am (UTC)
к слову, изначально я наткнулся на эту фичу в VHDL применительно к Xilinx'ам :-)
Денис: pic#118878298mithraen on January 25th, 2013 07:55 am (UTC)
Вот вечно разработчикам транзисторов на надежность жалко обозвали бы это значение NaN, вместе с корректной обработкой (любые операции над NaN дают NaN), и проблем бы не было. И было бы все логично: 0x7fff + 1 = NaN.
abs(NaN) = NaN.

Только это сломало бы другие хаки, где переполнение используют осознанно.
Nick Gavrikov: pic#74705469nickgavr on January 25th, 2013 08:17 am (UTC)
Сам знаешь, тогда мейнстримом была не надежность, а оптимизация.
Проверил ради интереса в C#, выдает исключение System.OverflowException: "Инвертировать минимальное значение двоичного дополнения невозможно"
Денис: pic#118878298mithraen on January 25th, 2013 08:54 am (UTC)
Тут вообще интересная штука -- сам по себе signed int это грязный хак, для процессора-то такого понятия вообще не существует. Это очередная сишная багофича. C это все-таки макроассемблер, требующий при написании очень хорошо понимать, что при этом происходит в реальности, и писать более-менее сложный корректный код на C не понимая во что он компилируется невозможно. Собственно потому никакого NaN быть и не могло -- когда создавался C в процессоре signed int не было, а в дальнейшем процессорам не было смысла иметь фичи несовместимые с C. Замкнутый круг идиотизма.

Я с такой же ненавистью все время вспоминаю ASCIIZ-строки, которые сейчас являются главной причиной большинства дырок в безопасности кода на C.

А еще изобретателям и внедренцам тредов предстоить гореть в аду за последствия их действий.

А вот в C#, интересно, исключение переполнения происходит если написать 0x7fffffffff + 1? Если да -- вот мы и приплыли, чтобы получить надежный код, приходится делать 100500 проверок уже на верхнем уровне, т.е. выбирать между тормозным кодом и ненадежным кодом.

И все равно проблема никуда не девается -- обрабатывать такие исключения мало кто будет.
Nick Gavrikov: pic#74705469nickgavr on January 25th, 2013 08:59 am (UTC)
не, получается 0x80000000 безо всяких исключений
Денис: pic#118878298mithraen on January 25th, 2013 09:01 am (UTC)
В общем как ни крути, а тип signed int это жуткая кривулька. И это никогда не будет исправлено.
А тип int -- просто кривулька. И это тоже никогда не будет исправлено.

А все IT создано из говна и палок, и нам приходится умудрятся делать из этого надежные системы :)
Nick Gavrikov: pic#74705469nickgavr on January 25th, 2013 09:06 am (UTC)
Кстати, я на x86-асме уже давненько ничего не писал, не помню. Но вот в AVR signed и unsigned очень даже различаются, все соответствующие команды продублированы

http://www.atmel.com/images/doc0856.pdf - поищи слово signed
Денисmithraen on January 25th, 2013 09:22 am (UTC)
Это прекрасно :)