1. C++ / Говнокод #16352

    +51

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    8. 8
    int table[4];
    bool exists_in_table(int v)
    {
        for (int i = 0; i <= 4; i++) {
            if (table[i] == v) return true;
        }
        return false;
    }

    C хабра. Возвращает true для любых чисел. http://ideone.com/bL2vGQ
    Я конечно знаю что такое UB, но этот пример повеселил.

    Запостил: kipar, 16 Июля 2014

    Комментарии (170) RSS

    • Ну это UB, само собой. Но почему true?!
      Ответить
      • Блин, цикл почему-то сканит всю оперативку пока не найдет или не упадет... UB'ы такие UB'ы... Объяснению не поддается.
        Ответить
        • Какие ваши доказательства, что цикл сканит всю оперативку?
          Ответить
          • По-моему он бы не укладывался в 0 секунд если бы сканил.

            На месте компилятора я бы рассуждал так - возвращаем
            (число в первых 4-х ячейках) || (UB)

            UB может быть и true и false, но если оно true, то мы можем оптимизировать функцию до одной строчки, а если false - придется перебирать первые элементы. Следовательно, будем считать его true.
            Ответить
            • Проверил, цикл действительно сканит всю оперативку, но только при выполнении двух условий:
              1. Условие завершения цикла i<=4.
              2. В цикле есть обращение к table[4].

              Почему обращение к несуществующему table[4] только на чтение что-то портит?
              Ответить
              • Ага, если сделать table[5] - начинает работать нормально.
                Ответить
              • > Почему обращение к несуществующему table[4] только на чтение что-то портит?

                Кмк, компилятор вворачивает какую-нибудь оптимизацию, которая отключает проверку в цикле. Я уже видел похожие прелести.

                Вероятно, он рассуждает примерно так:
                Хм, в массиве всего 4 элемента, i не может превзойти 3 физически, значит, уловие в цикле эквивалентно true (ведь программист не может быть дебилом, верно?). Пожалуй, заменю его на true, получу ПИРФОМАНС
                Ответить
                • В -O3 действительно перфоманс: конпелятор выпиливает цикл к чертям и получается так:
                  bool exists_in_table(int v)
                  {
                      if (table[0] == v) return true;
                      if (table[1] == v) return true;
                      if (table[2] == v) return true;
                      if (table[3] == v) return true;
                      if (table[4] == v) return true;
                      return false;
                  }


                  P.S. У меня 32-битный gcc не зацикливает с любыми ключами оптимизации. Проблема ideone или amd64?
                  Ответить
                  • > P.S. У меня 32-битный gcc не зацикливает с любыми ключами оптимизации. Проблема ideone или amd64?

                    А версии GCC точно одинаковые? Скорее всего, у одного из вас либо ещё нет этого бага, либо он уже починен.
                    Ответить
                    • Будем смотреть с помощью gcc.goldbolt.org, что выдают разные компиляторы.

                      GCC 4.9.0 и 4.8 с -O2 вообще всё выпиливает:
                      exists_in_table(int):
                      	movl	$1, %eax
                      	ret
                      С -O1 разворачивает цикл, как в моём примере.

                      А вот GCC 4.5, 4.6 и 4.7 с -O2 выдаёт подлинный говнокод:
                      exists_in_table(int):
                      	movl	$table, %eax
                      .L3:
                      	cmpl	%edi, (%rax)
                      	je	.L4
                      	addq	$4, %rax
                      	cmpq	$table+20, %rax
                      	jne	.L3
                      	xorl	%eax, %eax
                      	ret
                      .L4:
                      	movl	$1, %eax
                      	ret
                      Сравнивает указатель с указателем на конец массива, причём с помощью равенства (p == &table[4] вместо p > &table[3]), что и приводит к зацикливанию.

                      P.S. С -O1 ещё веселее: копирует 32-битные значения, а сравнивает 64-битные.
                      Ответить
                • мда, не угадал.

                  То, о чём я говорил, проявляется здесь:
                  http://ideone.com/J7HBhQ
                  http://users.livejournal.com/_winnie/426746.html?thread=5632506#t5632506
                  Ответить
                  • Holy Ffffuuu
                    Ответить
                  • Мир для меня никогда не будет прежним...
                    Ответить
                    • А что скажут санитайзеры шланга или просто -Wstrict-overflow=5?
                      Ответить
                  • У меня нет слов.
                    Ответить
                  • Вот еще пример:
                    int test(char *p) {
                        // программист не дурак, и NULL разадресовывать не будет
                        // а значит p - не нулл
                        int res = *p;
                        if (!p)
                            std::cout << "p is null" << std::endl;
                        else
                            std::cout << "p is not null" << std::endl;
                        return res;
                    }
                    К сожалению, этот UB всё-таки приводит к крашу, и результат невооруженным взглядом не увидеть... Но если посмотреть на сгенеренный код, то компилятор выкинул и условие и ветку с "p is null".
                    Ответить
                    • В блоге шланга был более интересный пример на эту тему: http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html
                      Ответить
    • Строгое равенство поставить и норм.
      Ответить
      • Спасибо! Сейчас попробую: http://ideone.com/9SzM3G
        Ответить
        • http://ideone.com/b1insT
          Ответить
          • Так не интересно! Код не царский!
            Ответить
            • Мне больше интересно какого ивана васиевича он всегда трет^W выдает тру.
              Ответить
              • >Мне больше интересно какого ивана васиевич
                kipar выше отлично все пояснил:
                http://govnokod.ru/16352#comment239843
                >UB может быть и true и false, но если оно true, то мы можем оптимизировать функцию до одной строчки, а если false - придется перебирать первые элементы. Следовательно, будем считать его true.
                Ответить
              • У меня два варианта ответа:
                1. Версии gcc >= 4.8 оптимизируют код до return true, вероятно, считая, что вероятность совпадения значения несуществующего элемента с введённым числом высока. Т. е. UB равно каждому введённому числу безо всякой случайности.

                2. Версии gcc от 4.5 до 4.7 тупо зацикливаются и сканируют оперативку, потому что оптимизируют условие выхода из цикла до строгого равенства.
                Ответить
                • > вероятно, считая, что вероятность совпадения значения несуществующего элемента с введённым числом высока
                  Походу компилятор рассуждает так: "Функция либо возвращает true на первых четырех итерациях, либо имеет UB. Программист не дурак, и UB не допустит, значит функция всегда возвращает true."
                  Ответить
    • >je .L4
      >jne .L3
      Никогда не понимал ну вот нахрена люди пишут выход из цикла по строгому равенству?
      for (int i=0;i!=n;++i)
      Или indexOf возвращает -1, я обычно стараюсь писать (indexOf()<0), на всякий случай. Те кто if (i=indexOf()!=-1) s.subString(i) должны страдать. Потому что когда-нибудь он может вернуть -2.
      Ну напиши, больше/меньше что тебе стоит. Не хотим, уверены что не переполнится и не проскочит через условие.
      Ответить
      • Это всё от неосиляторства полузакрытых интервалов [0, N), на которых построена половина STL.
        Ответить
        • Так то ж STL-итераторы - абстракция над указателями и индексами в массивах/строках. Как их применить к асму и адресной арифметике?
          Речь о числах.
          Сейчас надо кастануть Тараса, который расскажет что в Аде есть встроенные числовые типы с ограниченным интервалом.
          Ответить
          • > Так то ж STL-итераторы
            Дык а какая разница-то. Идея одна и та же: начинай с нуля и итерируйся до < END. Код в точности один и тот же что для итераторов, что для чисел.
            Ответить
            • Я совсем о другом.
              Разные числовые проверки , не только итерация. Можно использовать строгое равенство.
              Вот мы знаем что у нас конечная точка должа быть END, и сравниваем строго.
              if (x==END) break;
              А я говорю, неужели трудно сравнить if (x>=END) break;
              Такие проверки не раз выручали, когда в алгоритме выявлялись проёбы или он менялся, например, было i++, поменяли на i+=2 - можем проскочить END, если у него не та чётность.

              Пример c indexOf - это ведь не итерация, тут STL не поможет.
              Ответить
              • > Пример c indexOf - это ведь не итерация, тут STL не поможет.

                Да, тут виновата семантика indexOf.
                Кстати, std::string::find() возвращает исключительно положительные беззнаковые числа, а в случае провала возвращается максимальное беззнаковое число (по совместительству std::size_t(-1); предполагатеся, что таких больших строк не бывает). При таком раскладе идиома полузакрытых интервалов прекрасно работает.
                Ответить
                • >Да, тут виновата семантика indexOf
                  Не знаю. Это лучше исключений, и лучше подхода того же Go - возвращать джва значения в одном результат, в другом его успешность.
                  Всё-равно надо проверять и успешность, и валидность результата.
                  Концепция возврат явно невалидного значения, у сфейлившей функции (вернуть null, когда ничего не найдено) лично мне нравится.
                  Ответить
                  • > Концепция возврат явно невалидного значения, у сфейлившей функции лично мне нравится.

                    Семантически она ужасна. В качестве хака, нехило повышающего производительность, сойдёт.
                    Ответить
                    • >Семантически она ужасна.
                      А какие альтернативы?
                      Ну вернул невалидное. Если это сишка - надо всё-равно руками проверить код возврата/диапазоны.
                      Если в языке есть исключения зачастую внутри есть проверка - получим тоже исключение.
                      Ответить
                      • > А какие альтернативы?
                        В сишке - почти никаких. Там даже нельзя возвращать указатель вместо индекса, как в STL. Ибо конец строки быстро не получить :(

                        В более высокоуровневых языках - Maybe / Option(al), возможность ошибки должна проверяться на уровне типа.
                        Исключения в такие операции явно не вписываются.
                        Ответить
                        • И снова монады.
                          Так это просто обычная типобезопасная обёртка, содержащая указатель.

                          А вот частичные функции (для ограниченого подмножества аргументов заданного типа), из них можно извлечь какой-то профит?
                          Ответить
                          • > Так это просто обычная типобезопасная обёртка, содержащая указатель.

                            С точки зрения семантики "вернуть либо валидный индекс, либо ничего" и "вернуть число, возможно, индекс" - совершенно разные вещи. Первый вариант без проверки не скомпиляется, второй вариант скомпиляется без проблем. Ну и необходимость думать о виде неравенства сразу отпадает.
                            Ответить
                            • > Первый вариант без проверки не скомпиляется
                              А можно пример. Хотя бы на скакалке.
                              Ответить
                              • > А можно пример

                                мне лень писать код, идея должна быть ясна:

                                indexOf вызывается не просто так, мы как-то хотим использовать этот индекс. Взять substring, например. Но substring принимает Index, а не Maybe Index.

                                Т.е. с Maybe/Option нужно будет проверить полноту коробки и вытащить индекс, иначе типы не сойдутся.

                                Если же indexOf возвращает int, его можно совать в substring без каки-либо проверок, компилятору всё равно.
                                Ответить
                            • >С точки зрения семантики "вернуть либо валидный индекс, либо ничего" и "вернуть число, возможно, индекс"

                              А неправильное трактование. int воспринимается как целое и монолитное. А он им не является. На самом деле он составной, состоит из 32-х кусочков (bit).

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

                              Подобным образом в коллекциях я например возвращал индекс вставленного объекта плюс флаг - изменена этой вставкой коллекция или нет. Не плодить же ради этого структуру, или хуже того кортеж с боксингом. Альтернатива - джва вызова тоже отстой.
                              Ответить
                              • > А неправильное трактование

                                К сожалению, компилятор не обладает вашим воображением.

                                > Не плодить же ради этого структуру
                                >> В качестве хака, нехило повышающего производительность, сойдёт.
                                Ответить
                                • >> В качестве хака, нехило повышающего производительность, сойдёт.
                                  Не спорю.
                                  > компилятор не обладает вашим воображением.
                                  Шланг вероятнее всего i31 и i1 упакуeт.
                                  Ответить
                                  • > Шланг вероятнее всего i31 и i1 упакуeт.

                                    http://ideone.com/EZTSva
                                    Ответить
                                  • > Шланг вероятнее всего i31 и i1 упакуeт.
                                    Ой не факт, ой не факт... Если это локальные переменные, то он, скорее всего, тупо догонит их до разрядности проца (32 или 64) и будет прав.
                                    Ответить
                        • > В сишке - почти никаких.
                          Так ведь в сишке уже отработана концепция возврата натурального числа как результата успешно завершившейся функции и (не существующих в природе) отрицательных чисел как кодов ошибок.
                          И мне даже не жалко половины диапазона интов - пущай берут, у меня их ещё много :)
                          Ответить
                          • Дык это и есть тот самый "возврат явно невалидного значения у сфейлившей функции". А речь шла о том, что в сишке у него нет альтернатив.
                            Ответить
                            • > А речь шла о том, что в сишке у него нет альтернатив.
                              А errno?!
                              Можно конечно обсирать, но по сути точно так же и в асме - глобальный регистр статуса, и в каждом ядре свой (thread-local).
                              Не понимаю почему не сделали такой же глобальной переменной для регистра флагов.
                              Ну там бит переноса или переполнение подсмотреть - такое на всех платформах есть. Имхо, упростило бы жизнь.
                              Ответить
                              • А че errno? Его обычно не используют для сигнализации об ошибке. Как правило функция сигнализирует об ошибке возвращая кривое значение, а в errno лежит ее причина.

                                И вроде как значение errno не определено, если функция вернула корректное значение... Но я могу ошибаться.
                                Ответить
                              • Вот, пожалуйста, цитата из ERRNO(3):
                                Its value is significant only when the return value of the call indicated an error.
                                Ответить
                                • >Its value is significant only when the return value of the call indicated an error.

                                  Никто же не запрещает использовать в своих функциях для передачи ошибки. Главное задокументировать - проверьте errno.
                                  Ответить
                              • Имхо, в кишках винды более адекватный подход: все функции возвращают status code, а результат, если он есть, возвращается по ссылке через один из аргументов.
                                Ответить
                                • >возвращается по ссылке через один из аргументов
                                  А тех аргументов в winapi - тьма.
                                  Ну и по ссылке возвращать int из indexOf - извиняйте. Крестобляди такого не потерпят. Только стек, только хардкор.
                                  Ответить
                • > возвращается максимальное беззнаковое число (по совместительству std::size_t(-1);
                  std::string::npos
                  Уродливая хрень. Сравнивать с ним, имхо отстой.
                  Мда s.indexOf(find)<0 на беззнаковых не сработает. Я б наверное сделал так ~s.indexOf(find).
                  Ответить
                • >>Кстати, std::string::find() возвращает исключительно положительные беззнаковые числа, а в случае провала возвращается максимальное беззнаковое число (по совместительству std::size_t(-1);
                  >>максимальное беззнаковое число (по совместительству std::size_t(-1);
                  >беззнаковое число -1

                  О блядские кресты!!! Они там совсем ебанулись? Беззнаковый -1?!
                  Нет, ну так обосраться и получить underflow и/или конвертацию signed в unsigned прямо в доке.
                  static const size_t npos = -1;
                  Святое плюсодерьмо.

                  Культурный, образованный человек написал бы ~0. Но нахуя? Это слишком скушно. Вот -1 ведь гораздо интереснее, это резко повышает шансы разработчика проебать.
                  Ответить
                  • > конвертацию signed в unsigned прямо в доке
                    а что в этом страшного? конвертация сигнед в унсигнед, вроде, вполне известно задекларирована - беззнаковое представление должно тупо бит в бит соответствовать знаковому
                    другое дело, что -1 в прямом коде это 100...001, т.е. обожемой, сокращаем максимальный беззнаковый интервал в половину
                    и, самое печальное, все, кто пострадал от STL на архитектурах с прямым кодом, давно ликвидированы, и даже родственникам запрещено сообщать места их захоронений
                    Ответить
                    • > конвертация сигнед в унсигнед
                      Её следует избегать, как источник раздирающих жопу ошибок. И особенно необходимо избегать сравнений signed и unsigned.
                      Вот кто-то так же посудит и будет сравнивать с константой из доки:
                      s.indexOf(find)==-1
                      Оно заработает с неявной конвертацией, но это опасно.

                      Хотя бы тем что у такого как я есть желание поменять на s.indexOf(find)<0, -1 всегда меньше нуля. Так меня в школе обучали.
                      Ответить
              • I have been so beeridelwd in the past but now it all makes sense!
                Ответить
              • If your <a href="http://pxbskiseb.com">arlteics</a> are always this helpful, "I'll be back."
                Ответить
              • There's a secret about your post. ICHTBTIYTKY http://ogwkrf.com [url=http://uiulxho.com]uiulxho[/url] [link=http://fxcknhp.com]fxcknhp[/link]
                Ответить
          • Даже Паскале есть.
            Ответить
    • На кывте был тоже весёлый тред подобного типа, только там внутри брали не arr[i], а i*500000000, тоже компилятор генерировал совсем не то, что ожидалось.
      Ответить
    • мб table[4] и есть v, которая аргументом в стеке лежит?
      Ответить
      • Нет :) Почитай выхлоп жцц, удивишься.

        Вот он: http://goo.gl/u6Ahtt

        Либо в table есть 42 либо имеем UB. Значит в table есть 42.
        Ответить
      • Но ведь table определили вне функции. А идея интересная.
        Ответить
    • Меня один вопрос волнует - компилятор хотя бы сообщает про такое?
      Ответить
      • > компилятор хотя бы сообщает про такое?
        А ты как думаешь? :)
        Ответить
      • >Меня один вопрос волнует - компилятор хотя бы сообщает про такое?
        Нет. Если ты его не попросишь. Вежливо.
        Ответить
        • > Нет. Если ты его не попросишь. Вежливо.
          Но и тогда у него может быть плохое настроение, или ему будет просто лень ;)
          Ответить
          • Да. В примере Романа мне вообще не удалось добиться он него какого-либо ворнинга. (-Wall -Wextra -Wstrict-overflow=5)
            Именно за это все любят кресты.
            Ответить
            • http://ideone.com/zQg5M9
              Ответить
              • Где я уже такое видел.
                Ответить
                • В статье "A Guide to Undefined Behavior in C and C++" вестимо.
                  Ответить
              • дохуя умный компилятор
                Ответить
                • Как раз тупой, раз проебали такое. Хотя... мы ж не знаем какой код на машине допольнительный или обратный. Надо юзать с -ftrapv (креш) или -fwrapv - загадочно и двусмысленно документированой опцией, помогающей при таких раскладах
                  This option instructs the compiler to assume that signed arithmetic overflow of addition, subtraction and multiplication wraps around using twos-complement representation.
                  Особенно мне это нравится:
                  This flag enables some optimizations and disables other.

                  Ололо, КРЕСТОПРОБЛЕМЫ
                  This option is enabled by default for the Java front-end, as required by the Java language specification.
                  Ответить
                  • > Как раз тупой

                    слово "дохуя умный" не всегда является усиленной версией слова "умный"
                    Ответить
                    • Всегда наоборот
                      Ответить
                    • Понятно. Но как бы горе от большого ума, после abs всегда положительное и UB - проверку можно убрать.
                      Но если бы еще чуток умнее, то оставил хотя бы из тех соображений, что на данной конкретной машине используется вот такой код.
                      Ответить
                  • > Как раз тупой, раз проебали такое.
                    Не проебали, а выебнулись: если на входе Число Тараса - то при его отрицании имеем UB (всем похуй на результат), а для остальных чисел модуль всегда положителен, и позволяет убрать лишнюю проверку, в надежде на то, что программист опытный, и Число Тараса туда не передаст.

                    P.S. Но не самая приятная оптимизация, да.
                    Ответить
                    • >в надежде на то, что программист опытный,
                      Это умиляет.
                      Ответить
                      • Компилятор как бы намекает программисту "ну ты же умный, я тебе полностью доверяю", а когда тот отвернется и расслабится - ХУЯК ГРАБЛЯМИ ПО СПИНЕ КРОВЬ-КИШКИ-UNDEFINED-BEHAVIOR.
                        Ответить
                      • Скоро компиляторы будут форматировать диск при UB'ах, если посчитают это оптимальным решением. Благо стандарт позволяет.
                        Ответить
                        • компилинул кодца - соснул хуйца. it's a UB style! op! op op op op!
                          Ответить
                  • Not bad at all fellas and gasall. Thanks.
                    Ответить
                  • What a pleasure to find someone who iditeifens the issues so clearly http://mjlvsbbuekh.com [url=http://lcgnykpnhr.com]lcgnykpnhr[/url] [link=http://tmvrbpsdy.com]tmvrbpsdy[/link]
                    Ответить
        • Вежливые люди заставляют компиляторы работать. ОБСЕ отказывается комментировать ситуацию. Читать далее>>>
          Ответить
    • Возвращение карликового льва:

      http://ideone.com/CujF6o
      Ответить
      • Вот так ближе к реалу: http://ideone.com/OVgWdC
        Ответить
        • Это к чему вообще?
          Ответить
          • К теме об UB'ах.

            P.S. Кстати, никакие -fwrapv этот код не спасут - он просто перестанет выводить это число (т.к. abs(числа тараса) отрицателен). Так что даже не надейтесь отмахаться опцией ;)

            P.P.S. Да-да, жабисты, вас это тоже касается, причем еще больше, чем сишников - ибо в жабе нет unsigned.
            Ответить
            • число тараса - это число. в котором больше 100 символов?
              Ответить
              • Число Тараса это 2^(n-1), где n - разрядность числа. Например для uint32_t оно будет равно 0x80000000.
                Ответить
                • 100000....000? в двоичной. типа -0. UB среди чисел
                  Ответить
                  • Да. Минимальное отрицательное число в twos complement. Положительного аналога не имеет, отсюда и баги.
                    Ответить
                    • А в дотнете все норм

                      http://ideone.com/TFW7G7
                      Ответить
                      • Всё норм. http://ideone.com/VFmzO1
                        Ответить
                        • Никакого UB. все четко
                          -x = ~x+1
                          -(1<<31) = ~(1<<31)+1 = 01111111111111111....1 +1 = 1000000000000000...0

                          Все ок
                          Ответить
                          • В java и c# не бывает UB'ов, да. Вся математика работает строго по спеке. Вот только как это тебе поможет, если ты захочешь запилить вывод числа? :)

                            http://ideone.com/weT53G
                            http://ideone.com/t5b7T0
                            Ответить
                            • http://ideone.com/yQLBRA

                              Ответ прост - что бы сделать совместимость с костылем нужен еще один костыль
                              Ответить
                              • Ну тогда так:
                                if (x == -2147483648)
                                    buf = "-2147483648";
                                Ответить
                                • Хрен знает что хуже. Как говорил солист группы Бредор

                                  http://www.youtube.com/watch?v=giC3-LnnV4c
                                  Ответить
                            • интересная фигня

                              http://ideone.com/5XKhX0
                              Ответить
                              • Отформатируй код нормально, и интересная фигня превратится в унылую опечатку.
                                Ответить
                                • в смысле?
                                  Ответить
                                  • > в смысле?
                                    В прямом, блеать:
                                    private static void Main()
                                    {
                                        int k =0;
                                        for (int i=0; i<100; i++)
                                            k = k++;
                                        Console.Write(k);
                                    }
                                    Ответить
                                    • P.S. А, ты про то, что k = k++ не UB? Ну в шарпе и жабе вроде бы все тупо - операции выполняются в том порядке, в каком они выполнялись бы без оптимизаций. Т.е. сначала k++ увеличивает k и возвращает старое значение, а затем k = перетирает его старым значением.

                                      Хотя я бы на такой код тупо выдавал ошибку. Ибо такой код нинужен.
                                      Ответить
                                    • >> превратится в унылую опечатку.

                                      Так в чем опечатка то?)
                                      Ответить
                                      • Да я думал, что ты все итерации хотел посмотреть.
                                        Ответить
                                        • обижаешь. я все таки бакалавр, а не пес подзаборный)
                                          Ответить
                      • Всё норм. http://ideone.com/e05zBc

                        Я не спорю, исключение намного лучше, чем возврат хуйни. Но... в шарпике же есть unsigned. Почему бы не описать Math.Abs как unsigned Abs(int x)? Тогда вообще бы не было никаких проблем...
                        Ответить
                        • Всегда можно самому написать. В большенстве случаев это не нужно - кастовать туда-сюда почем зря тоже не айс
                          Ответить
                      • А в дотнете все норм
                        Угу, исключения на Math.Abs.
                        Ответить
                        • Те места, где действительно не хочется исключений, можно обернуть в unchecked().
                          Ответить
                          • Не знаю. Исключения для такой штуки как переполнение - неудобно, и вообще переголова.

                            Я бы сделал, повторюсь, доступные потоку флаги.
                            И не надо говорить что глобальное состояние не вписывается в реалии современного программинга .
                            Я даже знаю куда это положить: Thread.currentThread().wasOverflow()
                            Там же лежит Thread.currentThread().interrupt() - ставит точно такой же глобальный флаг прерывания, а Thread.currentThread().isInterrupted() читает этот флаг.
                            Глобальное (per-thread) мутабельное состояние. И ничё.

                            А в жабе вообще нет встроенных средств произошло ли переполнение при умножении например. Существуют конечно байтоебские приемы, но процессор ведь это уже посчитал. Зачем извращаться?
                            Ответить
                            • > Исключения для такой штуки как переполнение - неудобно, и вообще переголова.
                              Дык оборачивание в unchecked() переключает режим обработки с trap на wrap. И никакой переголовы не остается. Байтоёбствуй сколько душе угодно.

                              А для остальных случаев, где не байтоёбство, а именно операции с целыми числами, исключение на переполнениях само то: и кривую хуйню случайно не вернет, и никакие флаги программисту проверять не надо.
                              Ответить
                              • Иногда при байтоебствовании хочется понимать было переполнение/перенос или нет.
                                Пример: реализация арифметики очень больших целых.
                                Переполнение тут не исключительная ситуация, а вполне повседневная часть алгоритма.

                                > а именно операции с целыми числами, исключение на переполнениях само то
                                Вероятнее тут одно из двух - или инструмент выбран неправильно - вам не нужны целые числа, а нужна длинная арифметика, или всё же ошибка переполнения не нужна. Хотя всякое бывает, и исключения могут быть полезны.
                                Ответить
                                • > Пример: реализация арифметики очень больших целых.
                                  Согласен, но не совсем. Есть carry (который как раз повседневная часть алгоритмов - лишний бит вылез за разрядную сетку), а есть overflow (который только для знаковых интов, и, имхо, таки исключительная ситуация - знаковый бит запороло переполнением из предыдущего разряда).
                                  Ответить
                                  • P.S. И вот все эти сложения длинных чисел проще всего мутить на unsigned'ах и carry (если бы он был доступен). А знаковые int'ы с их переполнениями и прочими тараканами там нахуй не сдались.
                                    Ответить
                                    • А если нужно вычесть 10000000000000000000000000 из 10000000000000000000?

                                      помню лет 6 назад мутил длинную арифметику на строках - такое говнецо я вам скажу
                                      Ответить
                                      • > А если нужно вычесть 10000000000000000000000000 из 10000000000000000000?
                                        Дык логически это большое число - знаковый int в twos complement или sign-magnitude. А вот физически это пачка unsigned'ов.

                                        Поэтому с результатом всё будет норм, но в промежуточных рассчетах всё будет беззнаковым.

                                        > длинную арифметику на строках
                                        Да, это тот еще гемор... Равно как и BCD. Да и имеет смысл только если десятичное i/o происходит на порядок чаще чем расчеты. Т.е. чуть менее, чем никогда.
                                        Ответить
                                        • А, по есть по сути новый тип для длинной арифметики, который скрывает все говно и выглядит как набор длинного без знака и флага. Или может я не понял, я не уверен что понял.
                                          Ответить
                                          • > который скрывает все говно и выглядит как набор длинного без знака и флага
                                            Я нихуя не понял, если честно ;) Ты о том, что эту реализацию он должен скрывать от всех? Ну да. И флаг у него там или twos complement - всем пофиг. Для юзеров библиотеки он выглядит как хаскелевый Integer или жабий BigInteger - просто большой, знаковый и удобный.
                                            Ответить
                                            • Я прочитал "беззнаковый" поэтому флаг наружу вывесил. Значит я все правильно понял. Мы инкапсулируем все говно внутри и никому его не показываем, а снаружи мы мягкие и пушистые. Как карм.... Стоп
                                              Ответить
                                              • Мой горячий карманный лев ждёт, когда ты погладишь ему гриву...
                                                Ответить
                                    • >Есть carry (который как раз повседневная часть алгоритмов - лишний бит вылез за разрядную сетку), а есть overflow
                                      >>Иногда при байтоебствовании хочется понимать было переполнение/перенос или нет.
                                      Лично мне не помешало бы и то, и другое, хотя чем overflow в unsingned не carry? При том что кодер знает что только что он складывал числа.

                                      >если бы он был доступен
                                      В этом и проблема.
                                      Ответить
                                      • > чем overflow в unsingned не carry
                                        Тем, что после него потом еще и знак выправлять у переполнившегося числа.
                                        Ответить
                                        • >Тем, что после него потом еще и знак выправлять у переполнившегося числа.
                                          unsigned же.
                                          Ответить
                                          • > unsigned же.
                                            А у unsigned'а в принципе не бывает overflow (переполнения) у него может быть только carry (перенос).
                                            Ответить
                                            • >А у unsigned'а в принципе не бывает overflow (переполнения)
                                              Да неужели?
                                              Ну вообще-то это называется переполнение, потому что тип конечный.
                                              За пруфами гуглить unsigned integer overflow.
                                              >в принципе не бывает overflow (переполнения)
                                              Или надо предоставить контрпруф.
                                              Ответить
                                            • >А у unsigned'а в принципе не бывает overflow (переполнения)
                                              Собственно из определения термина переполнение понятно: оно возникает когда результат не может быть выражен величиной регистра. unsigned совсем не означает безразмерный.
                                              Ответить
                                              • Ну ок, ок... Но если в unsigned'е это переполнение можно юзать во благо - для переноса в следующий разряд. То в signed'е это именно исключительная ситуация - знаковый бит распидорасило. Да, и там можно пофиксить знаковый бит и перенести куда-нибудь зародившийся 31й бит... Но нахер надо? Никто не собирает длинные числа из знаковой хероты - ведь это получится либо использование его как 31-битный unsigned, либо извращенное представление, допускающее и + и -.

                                                P.S. Что-то я становлюсь похож на царя с этими unsigned'ами...
                                                Ответить
                                              • Ну в общем:
                                                - для байтоёбства - unsigned only в режиме unchecked (да, жаль, что флаг недоступен)
                                                - для вычислений с небольшими числами - signed и unsigned в режиме checked (т.к. wraparound здесь нахуй не сдался, и исключение никому не помешает).
                                                - для вычислений с большими числами - класс для больших чисел

                                                P.S. А JIT шарп'а умеет превращать конструкции вот такого типа во флагоёбство?
                                                ulong p; // перенос
                                                p += a[i] + b[i];
                                                c[i] = p & 0xFFFFFFFF;
                                                p >>= 32;
                                                Ответить
                                                • P.S. gcc тоже не умеет :( 64 битное сложение получилось. Ну вернее что-то типа такого:
                                                  add p_low, a[i]
                                                  adc p_high, 0
                                                  add p_low, b[i]
                                                  adc p_high, 0
                                                  mov c[i], p_low
                                                  mov p_low, p_high
                                                  Ответить
                                    • Сравнение джвух подходов. Шарпоблядство выглядит сильно громоздко.
                                      //ШАРПОБЛЯДСТВО
                                      try   
                                      {
                                          checked
                                          {
                                              uint r = a+b;
                                          }
                                      }
                                      catch (OverflowException exc)
                                      {
                                         //обрабатываем
                                      }
                                      //БАЙТОЕБСТВО
                                      uint r = a+b;
                                      if ((a>~b))
                                      {
                                         //обрабатываем
                                      }
                                      Короче, нахер исключения.
                                      Ответить
                                      • Vanished
                                        Ответить
                                      • Интересная цитатка попалась: Of course, many processors don't have a carry flag at all (MIPS, Alpha), some have one carry flag but lots of other flag registers (PowerPC) and ARM has a carry flag that works the opposite way sometimes.

                                        Если это правда, то оптимальное сложение BigInteger'ов можно накодить только на асме, под каждую конкретную платформу :(
                                        Ответить
                                        • Ну да. А потом виртуальную машину и jit компиляцию по все виды процов. А потом и жабу на нее. Или это уже было?
                                          Ответить
                                        • > можно накодить только на асме, под каждую конкретную платформу :(
                                          Пишем один универсальный для получения флага, и ifdefами частные варианты под платформу. JIT, когда увидит в байт-коде использование флага, скомпилирует его вычисление.

                                          >processors don't have a carry flag at all (MIPS, Alpha)
                                          А overflow? А как mono будучи портируемым на эти платформы будет проверять переполнение?
                                          Ответить
                                      • А сопроводжаемость кода как же?
                                        Ответить
                                        • > А сопроводжаемость кода как же?
                                          Берешь и сопровождаешь все варианты ;)

                                          Тут либо байтоёбство и скорость, либо универсальность и удобство правки... Третьего не дано.
                                          Ответить
                                          • Ну да. Я о том, что все зависит от типа проекта. Байтоебить - так байтоебить. Но нахрен байтоебить в шарпе?

                                            Из третьего выходит говно в стиле - отлаживаем производительность. там, где она и так высока, а на узкое место кладем хуй
                                            Ответить
                                        • >А сопроводжаемость кода как же?
                                          >>if ((a>~b))
                                          Дооо. Это чрезвычайно трудно сопровождать.
                                          Ответить
                                          • >>Короче, нахер исключения.
                                            >А сопроводжаемость кода как же?

                                            Конечно иногда приятно поебать байты и покушать ежа, но и меру нужно знать
                                            Ответить
                  • Apeorciatipn for this information is over 9000-thank you!
                    Ответить
                  • Hot damn, loknoig pretty useful buddy. http://xhdminkyvbe.com [url=http://uicuxwxko.com]uicuxwxko[/url] [link=http://ozmvuxjjsnr.com]ozmvuxjjsnr[/link]
                    Ответить
            • > он просто перестанет выводить это число (т.к. abs(числа тараса) отрицателен).
              Ну это уже много раз разбирали.
              >-fwrapv этот код не спасут - он просто перестанет выводить это число (т.к. abs(числа тараса) отрицателен).
              Это вполне очевидное и ожидаемое поведение.
              > Да-да, жабисты, вас это тоже касается, причем еще больше, чем сишников
              Практически всех касается.
              >числа тараса
              Откуда название?
              Ответить
              • от тараса
                Ответить
              • > Откуда название?
                Тарас вроде какой-то ГК с ним постил. Или в пример его приводил... Не помню уже...

                P.S. Шарпье исключение, имхо, поадекватней чем минус без числа ;) Сразу видно, что нарвались на косяк.
                Ответить
                • >Тарас вроде какой-то ГК с ним постил. Или в пример его приводил...
                  Не Тарасом единым. Уже очень давно постилось на гк.
                  >Шарпье исключение, имхо, поадекватней чем минус без числа ;)
                  Уже надоело этот ГК #3117 приводить в пример.
                  Ответить
                  • Нахуй там вообще этот abs при сидировании генератора? И так сидов мало, так еще и половину проебали...
                    Ответить
                • Мне другое непонятно. Почему не one's complement не прижился? Зачем нужно удлинять тип на 1/4 миллиардную?
                  И читать отрицательные проще, и проблемы нет. Ну да, отрицательный ноль, но мы и покруче видали в IEEE 754:
                  sqrt(-0) == -0
                  Ответить
                  • >>sqrt(-0) == -0

                    моя реакция:
                    (-0) == -0
                    Ответить
                  • > Почему не one's complement не прижился?
                    Может быть арифметика сложнее получается? Лень сейчас думать-вспоминать, но вроде бы там вычитатель через тупой сумматор уже не замутить?
                    Ответить
                    • >Может быть арифметика сложнее получается? Лень сейчас думать-вспоминать, но вроде бы там вычитатель через тупой сумматор уже не замутить?
                      Да. Так и есть.
                      Считать внутри как удобно. Но! Поставить на выходе копеешную схему преобразования в обратный код, а на входе в дополнительный
                      Или допустим VM проектируют, ведь биты их можно интерпретировать как угодно.
                      Вот в жабе говорите нет unsigned, нет типа, для гурманов появились байтоебские методы которые трактуют int как unsigned и могут делить/умножать/печатать.
                      Ответить
                      • > Поставить на выходе копеешную схему преобразования
                        Ну, видимо, в то время, когда все это выбиралось - это было слишком дорого... А теперь уже слишком поздно. Кресты то все стерпят, они и с ones complement работать будут (хоть и с горением жоп у тех, кто юзал UB'ы с переполнением int'ов и касты отрицательных int'ов в unsigned). А вот у жабы и шарпа в спеке навсегда увековечено twos complement.
                        Ответить
                        • кресты и с прямым кодом будут, это вам не какое-то там анальное архитектурное рабство!
                          this International Standard permits 2’s complement, 1’s complement and signed magnitude representations for integral types
                          Ответить
                          • И даже девятибитные байты...
                            Ответить
                            • девятый бит несет в себе информацию, что он девятый бит
                              Ответить
                              • нет, он несет в себе свое значение, как и другие его соседи
                                об этом есть в стандарте
                                Ответить
                                • Даже есть шуточный стандарт rfc4042 по UTF-9 и UTF-18. На PDP-10 с его 36-битным словом другие варианты будут расточительством.
                                  Ответить
                          • Боги битоебства делятся с нами своей мудростью:
                            The myth that any given programming language is machine independent is easily exploded by computing the sum of powers of 2.
                            If the result loops with period = 1 with sign +, you are on a sign-magnitude machine.
                            If the result loops with period = 1 at -1, you are on a twos-complement machine.
                            If the result loops with period > 1, including the beginning, you are on a ones-complement machine.
                            If the result loops with period > 1, not including the beginning, your machine isn't binary -- the pattern should tell you the base.
                            If you run out of memory, you are on a string or Bignum system.
                            If arithmetic overflow is a fatal error, some fascist pig with a read-only mind is trying to enforce machine independence.
                            But the very ability to trap overflow is machine dependent.
                            By this strategy, consider the universe, or, more precisely, algebra:
                            let X = the sum of many powers of two = ...111111
                            now add X to itself; X + X = ...111110
                            thus, 2X = X - 1 so X = -1
                            therefore algebra is run on a machine (the universe) which is twos-complement.
                            Крестухи опять соснули особенно учитывая тупые проебы в других частях языка, что абсолютно верно подмечено выше:
                            >другое дело, что -1 в прямом коде это 100...001, т.е. обожемой, сокращаем максимальный беззнаковый интервал в половину
                            >и, самое печальное, все, кто пострадал от STL на архитектурах с прямым кодом, давно ликвидированы, и даже родственникам запрещено сообщать места их захоронений
                            Ответить
                            • Лоханулись составители стандарта здесь только в том, что сдуру записали максимальное значение unsigned'а как -1. Можно ж было вот так написать:
                              static const size_t npos = std::numeric_limits<size_t>::max();
                              И код вообще перестал бы зависеть от реализации знаковых чисел на целевой платформе. Никаких половин диапазонов и т.п.

                              Как вариант - можно было остановиться на том, что npos это максимальное значение size_t, и вообще не писать, как его получают в домашних условиях.
                              Ответить
    • показать все, что скрытоУгадайте, что я въебал этому посту.
      Ответить

    Добавить комментарий