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

    +63

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    #include <iostream>
    using namespace std;
    
    int main() {
    	// your code goes here
    	float f = 267.0f;
    	unsigned char c = f;
    	cout << (int)c << endl;
    	return 0;
    }

    Кресты помогают обнаруживать ошибки в логике программы. За это Страуструпу респект и уважуха.

    http://ideone.com/V9rgSC

    Запостил: LispGovno, 09 Февраля 2014

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

    • Ответить
    • Эээ... Но почему 255?!

      Хм, у меня 11 вывело, как я и ожидал.
      Ответить
      • Ой лол. На -O2 действительно 255. Причем намертво вкомпиленное в код.

        Баг gcc? Или так и положено по стандарту?
        Ответить
        • 4.9 Floating-integral conversions [conv.fpint]

          1. An rvalue of a floating point type can be converted to an rvalue of an integer type. The conversion truncates; that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be represented in the destination type.

          Вот так вот :(

          Ну вообще говоря и 255 и 11 вполне осмысленные ответы, вот только компилятор, сука, мог бы и предупредить. На целых числах же про truncation постоянно ругается.
          Ответить
          • При включенном -Wconversion матерится, все норм.
            Ответить
        • Причём если сделать
          float f;
          std::cin >> f;
          и ввести 267, то выйдет 11 даже на О2.

          Вывод: видим при компиляции, что происходит переполнение — заменяем жёстко на UCHAR_MAX. В рантайме — как байты лягут.

          Отличный пример. Утащил для наглядной демонстрации UB.

          Кстати, а что альтернативные компиляторы? Студия ругается?
          Ответить
          • > float f;
            > std::cin >> f;
            http://ideone.com/nvjdXC
            Где UB?
            Ответить
            • Я имел в виду заменить строку float f = 267.0; на это. При преобразовании в чар выйдет УБ
              Ответить
              • Без варнингов?
                Ответить
                • Как и в оригинальном коде, без варнингов на -Wall -Wextra. Я же только добавил получение значения из стандартного ввода, чтобы убрать явные оптимизации компилятора.
                  http://ideone.com/LbogiH

                  Как Борманд выше сказал, нужно компилировать с -Wconversion, чтобы получить варнинг.
                  Ответить
                  • Хрена себе. Я всегда считал, что достаточно компилировать с -Wall -Wextra -Pedantic чтобы получить все возможные варнинги. Интересно, что ещё кроме этих ключей ещё нужно написать, чтобы получить полный список проверок?
                    Ответить
                    • Все отсюда http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
                      Вообще не хватает опции -Weverything
                      Ответить
                      • -Wall
                        -Weverything
                        -Wreallyeverything
                        -Weverythingandskyandallah
                        Ответить
                        • Я однажды на вижуал студии включил /Wall.
                          Получил сотни подобных ворнингов:

                          C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\limits(1270) : warning C4514: 'std::numeric_limits<double>::signaling_ NaN' : unreferenced inline function has been removed
                          Ответить
                          • Ты не путай чоткий гцц и студию не умеющую в варнинги нормально. Ну и совсем унылые варни, какие не хочется исправлять или помечать как корректные - можно отключить
                            Ответить
                          • В студии по дефолту включены вообще не те ворнинги, от которых польза.
                            Ответить
                            • > В студии по дефолту включены вообще не те ворнинги, от которых польза.
                              Просто студия не умеет разделять ворнинги на пользовательские и системные. И показывает юзеру тонны ворнингов из своих же хидеров.

                              gcc по дефолту так не делает, и поэтому там нет этой проблемы с портянкой бесполезных предупреждений.
                              Ответить
                              • У gcc во всех хидерах написано
                                #pragma GCC system_header
                                Если я не ошибаюсь буст так же подавляет варнинги в себе
                                Ответить
                              • >хидеров
                                Почему header читается как хидер?
                                Ответить
                              • Да я не думаю, что ты захочешь читать об неиспользованных шаблонных функциях даже в собственном коде.
                                Ответить
                                • Ну особо нозящие и бесполезные ворнинги можно же отключить дополнительными опциями.
                                  Ответить
                                  • Мой посыл был в том, что в VS /Wall - это включить вообще всё-всё-всё возможное. Некоторые предупреждения оттуда, скорее, не предупреждения вовсе, а некий отладочный вывод, интересный энтузиастам и разработчикам компилятора.
                                    Ближе к GCC'шному -Wall будет, пожалуй, /W4.
                                    Ответить
                          • Ну не, варнинги, с которыми нельзя писать никакой вменяемый шаблонокод - не нужны.
                            Ответить
                      • Там большой список, пол ночи буду читать. Что-бы получить реально все варнинги -Weverything какие ключики нужно перечислить?
                        Ответить
                        • >Что-бы получить реально все варнинги -Weverything какие ключики нужно перечислить?
                          Человеку много пишущему/компиляющему на крестах надо знать как таблицу умножения. Имхо азы.
                          Откройте же для себя наконец SO.

                          -Wextra, -Wall: essential.
                          -Wfloat-equal: useful because usually testing floating-point numbers for equality is bad.
                          -Wundef: warn if an uninitialized identifier is evaluated in an #if directive.
                          -Wshadow: warn whenever a local variable shadows another local variable, parameter or global variable or whenever a built-in function is shadowed.
                          -Wpointer-arith: warn if anything depends upon the size of a function or of void.
                          -Wcast-align: warn whenever a pointer is cast such that the required alignment of the target is increased. For example, warn if a char * is cast to an int * on machines where integers can only be accessed at two- or four-byte boundaries.
                          -Wstrict-prototypes: warn if a function is declared or defined without specifying the argument types.
                          -Wstrict-overflow=5: 
                          -Wwrite-strings: give string constants the type const char[length] so that copying the address of one into a non-const char * pointer will get a warning.
                          -Waggregate-return: warn if any functions that return structures or unions are defined or called.
                          -Wcast-qual: warn whenever a pointer is cast to remove a type qualifier from the target type*.
                          -Wswitch-default: warn whenever a switch statement does not have a default case*.
                          -Wswitch-enum: warn whenever a switch statement has an index of enumerated type and lacks a case for one or more of the named codes of that enumeration*.
                          -Wconversion: warn for implicit conversions that may alter a value*.
                          -Wunreachable-code: warn if the compiler detects that code will never be executed*.
                          http://stackoverflow.com/a/3376483
                          http://stackoverflow.com/questions/154630/recommended-gcc-warning-options-for-c
                          Ответить
                          • А как же
                            -Weffc++
                            -Pedantic
                            ?
                            Ответить
                            • -WTarasB
                              Ответить
                              • Между прочим похоже. Это вроде от Меерса 10 варнингов из Эффективное использование С++
                                Ответить
                              • Включает режим, при котором выдаёт предупреждения на все конструкции, имеющие не паскальную семантику.
                                Ответить
                            • По ссылкам есть. Просто на гк ограничение на текст коммента.
                              Ответить
                    • Да тут видишь что, по дефолту отключены проверки у которых тонны false-positive. С тем же -Wconversion ты затрахаешься ставить явные касты где надо и где не надо...

                      Ну а список ворнингов есть на сайте gcc, выбери те, которые не будут тебя бесить ;)
                      Ответить
                      • Как раз сейчас на крестофоруме срач про неявные касты: http://www.gamedev.ru/flame/forum/?id=185849
                        Особенно про неявный каст инта в флоат. Я считаю, что тот, кто брезгует явно приводить тип - недостойный говнокодер.
                        Ответить
                        • > Я считаю, что тот, кто брезгует явно приводить тип - недостойный говнокодер.
                          А смысл? Ну будут люди на автомате бездумно втыкать касты где надо и где не надо... Никаких проблем это не решает. Разве что страхует от случайных опечаток.

                          А каст одинаково плох что в явной форме, что в неявной - он скрывает семантику преобразования. Тот же каст флоата в инт - что он должен олицетворять? floor? ceil? round? Банковское округление? Каст целого в меньшее - обрезать биты, подставить максимум, или вообще кинуть исключение? Каст числа в строку - как именно форматировать ее? Каст чего-то в бул - почему именно эти значения являются false? Особенно это касается слабой тупизации аля PHP, где "0" считается за false, "0.0" за true, а 0.0 за false.

                          Так что все касты (включая явные) надо тупо закопать, а вместо них дать набор функций с четкой и ясной семантикой.
                          Ответить
                          • P.S. Неявные касты целых чисел в бОльшие и ссылок на объекты в ссылки на их родителей можно оставить, они никому не навредят, только добавят читабельности.

                            Ну и dynamic_cast оставить, т.к. он и есть та самая функция с понятной семантикой. И заменить его нечем.
                            Ответить
                            • >Неявные касты целых чисел в бОльшие
                              Это тоже не надо. От тупого присваивания беды не будет, а вот от логических битоебских операций между лонгом и интом я когда-то пострадал.
                              int a=3;
                              <.дохера кода.>
                              long mask=3<<shift; //где shift [0..63]
                              long res=mask & a; //лучше бы тут был ворнинг
                              Ответить
                              • Знакомо, мне тоже причиняло бугурт то что даже 2 short int при использовании побитовых операций дают на выходе полный int.
                                Ответить
                              • А я не врубился, а что произошло-то?
                                если shift хотя бы 32, то res обнуляется, да?
                                И вообще если shift хотя бы 2, то res обнуляется.
                                А что не так-то?
                                Ответить
                                • > если shift хотя бы 32, то res обнуляется, да?
                                  Нет. Сдвиг на число, большее нежели разрядность - в крестах и сишке UB (в яве не UB, но я не помню что конкретно).

                                  На х86 результат не зануляется, а просто сдвигается на shift & 31 (если число было 32 битным).

                                  На других архитектурах может и занулиться.

                                  UPD: В жабе та же херня: If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance. If the promoted type of the left-hand operand is long, then only the six lowest-order bits of the right-hand operand are used as the shift distance..
                                  Ответить
                                  • А, так сначала приведи к лонгу, потом двигай, не?
                                    Ответить
                                    • > А, так сначала приведи к лонгу, потом двигай, не?
                                      Да, об этом и говорил Пи. Если бы не было неявного каста инта в лонг - компилятор бы его обматерил. А т.к. неявный каст есть - сдвинуло инт как попало, а потом привело к лонгу.
                                      Ответить
                          • Добавить шаблонных параметров в static_cast и всего делов.
                            Ответить
                          • Каст - говно. Эти скобки мне при первом изучении и прочтении взорвали моск.
                            Как это гуглить начинающему?

                            >>Так что все касты (включая явные) надо тупо закопать, а вместо них дать набор функций с четкой и ясной семантикой.
                            Да-да-да. +100500.
                            Функции и гуглятся, и семантика определена, и каст в целом сахар от которого толстеет язык.
                            Сахар, который можно заменить стандартным средством композиции.
                            Ответить
                          • PS. В той же жаве гораздо проще и понятнее писать через женерик хелпер-метод:
                            SomeAbstractShit a=cast(b).getA();
                            чем
                            SomeAbstractShit a=((SomeAbstractShit) b).getA();

                            Посему выжигать сишкоблядское наследие.
                            Ответить
                            • мне нравится синтаксис приведения типов в Go:
                              b.(SomeType).GetA()
                              Ответить
                              • Как какшка какая-то. В обоих языках. Что тут происходит и почему именно так?
                                Ответить
                              • Опять-таки. Это нельзя нагуглить.
                                Ответить
                          • это недостаток компилятора, раз он не может обратить внимание на ub приведения явно большего в явно меньшее

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

                            поэтому мне неведомо насколько часто хочется в типичном гейпроекте ААА приводить float в int - неужели постоянно?
                            Ответить
                            • У меня в геймдеве под мобилки плавающий питух отсутствует.
                              Ответить
                            • > приводить float в int - неужели постоянно
                              У нормальных кодеров - никогда ;)

                              Округлить число по неким правилам - всяко часто. А "инт мне запили" - никогда. И если кто-то видит в (инт)4.5 "приведение флоата к целому" - он, имхо, упоротый идиот.
                              Ответить
                              • float a;
                                ...
                                BigInteger b = BankRound(a);
                                Ответить
                              • float Q_rsqrt( float number )
                                {
                                	long i;
                                	float x2, y;
                                	const float threehalfs = 1.5F;
                                 
                                	x2 = number * 0.5F;
                                	y  = number;
                                	i  = * ( long * ) &y;                       // evil floating point bit level hacking
                                	i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
                                	y  = * ( float * ) &i;
                                	y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
                                //      y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
                                 
                                	return y;
                                }
                                Ответить
                                • Ну и тут тоже не просто бессмысленное "запили мне инт из флоата". Тут "запили мне инт, имеющий то же двоичное представление, что исходный флоат".
                                  Ответить
                                • reinterpret_cast
                                  Ответить
                              • Я Упоротый идиот - я еще и так писал int(k+0.5)//округление.
                                З.Ы. А в чем проблема вообще?
                                Ответить
                                • -1.4 округлится к нулю
                                  Ответить
                                • > А в чем проблема вообще?
                                  Есть разные виды округлений - в меньшую сторону, в большую, к нулю, банковское и т.п.

                                  Одно из них непонятным образом (видимо подбрасив монетку) выбрали и сделали округлением по умолчанию, назвав "приведением флоата к инту".

                                  Если кто-то в приведении флоата к инту видит не конкретный способ округления, принятый в данном языке, а неведомое "превращение флоата в инт" - он упорот.
                                  Ответить
                        • А еще надо урезать unsigned на 1 бит, чтобы народ прекратил его абузить, и применял unsigned только ради беззнаковости, а не ради лишнего бита.

                          Как вариант - можно выпилить нахер unsigned числа, и дать возможность указывать диапазон (в аде так и было?).

                          P.S. Жду недовольства сишников ;)
                          Ответить
                          • >можно выпилить нахер unsigned числа
                            Запретить перегрузку операторов, добавить GC, убрать множественное наследование (за исключением чисто абстрактных классов), избавиться от системы с заголовочными файлами, и получится Ява
                            Ответить
                            • > избавиться от системы с заголовочными файлами
                              В яве тоже говно с модулями :( Не до конца довели идею, остановились на сраной неверсионированной помойке под названием CLASSPATH.

                              Вот в дотнете с их assembly уже близко к идеалу.
                              Ответить
                            • >добавить GC
                              Никто за то не говорил.
                              >убрать множественное наследование (за исключением чисто абстрактных классов),
                              В сишке нет ООП.

                              >избавиться от системы с заголовочными файлами
                              А еще нормальные макросы, упрощения, женерики.
                              И получится простой, охуенный низкоуровневый язык который все ждали.
                              Ответить
                          • >>можно выпилить нахер unsigned числа

                            В JDK 8 пошли самым кошерным путём (не расширяя при этом язык), сделали методы (mul,div,toString) которые трактуют int, long как беззнаковые.

                            От unsigned проблем больше, имхо. Причем вот даже если борманд такое говорит.
                            Ответить
                            • какие проблемы от unsigned?
                              если жава во что-то не умеет, то это автоматически становится ненужным, бугага

                              как ты собираешься представлять непрерывный бинарный поток, через signed char?
                              Ответить
                              • Ну вот с unsigned char'ом аля byte есть проблема, тут не поспоришь :(
                                Ответить
                                • Какая проблема? Знаковый символ - ок. Да и знаковый byte тоже не так уж и плохо.
                                  Ответить
                                  • Сравнивать неприятно, в инт раскастовывается криво (хотя если были бы 2 отдельных функции вместо каста (например ubyte2int и sbyte2int) - было бы норм даже со знаковым.

                                    > Знаковый символ
                                    Символ, имхо, вообще не надо смешивать с байтами. Это атавизм из старых добрых времен, когда кодировки были однобайтовыми. Поэтому только chr(), только ord(), только хардкор.
                                    Ответить
                            • Как ты всю память собрался адресовывать без unsigned? Ну вот завел я deque на 2,1 Gb. Что дальше? 3Gb режим адресного пространства в винде возможный не забывай
                              Ответить
                              • твои доводы нелепы до безобразия
                                в жабе deque на 2.1 Gb - это как минимум 20 гигов памяти
                                т.е. уже по-любому 64-разрядная ОС и => uint64_t вновь ненужен
                                Ответить
                              • > 3Gb режим адресного пространства в винде возможный не забывай
                                Ты хочешь запилить один массив на 2+ гигачара? Других случаев, когда тебе понадобится size_t >= 2^31 я не вижу.
                                Ответить
                                • И вообще зннаковый инт для массивов удобнее.
                                  -1 - сразу ясно, что это сознательно выставили значение "невозможный индекс", как НУЛЛ.

                                  А в беззнаковом нету "НУЛЛ-индекса"(

                                  Кто скажет про то, что меньше букв писать в проверке индекса - тот лох.
                                  Ответить
                                  • >>-1 - сразу ясно, что это сознательно выставили значение "невозможный индекс", как НУЛЛ.
                                    Тут видна подспудная ненависть Тараса к исключениям. И вот тут он как раз прав.
                                    Ответить
                                    • а вообще, так как часто структуры по умолчанию заполняют нулями, лучше бы подошли массивы, нумеруемые с 1
                                      Ответить
                                      • namespace std_with_indexes_staring_from_one
                                        {
                                        template <typename T>
                                        class array
                                        {
                                        //...
                                            T& operator[](size_t index)
                                            {
                                                return data[index-1];
                                            }
                                        //...
                                        };
                                        
                                        template <typename T>
                                        class vector
                                        //...
                                        
                                        }
                                        Ответить
                                      • Напомнило пост, который я где-то видел. "10 вещей, которые стоит улучшить в котах". Там после десятого улучшения получилась собака.
                                        Так и у Тараса, после стопицотого улучшения Си выйдет Паскаль.
                                        Ответить
                                        • >> "10 вещей, которые стоит улучшить в котах". Там после десятого улучшения получилась собака.

                                          Если в слове "сишка" сделать 5 ошибок, то получится "говно".
                                          Ответить
                                          • >"сишка"
                                            Вернее я хотел сказать "кресты"
                                            Ответить
                                          • Это не "сделать ошибки в названии", а "исправить ошибки в названии".
                                            Ответить
                      • А в Паскале вместо false-positive-ворнингов расстрел. Там по ошибке флоат в инт не засунешь...
                        Ответить
                        • В жабе даже дабл во флоат не засунешь ;)
                          Ответить
                          • Да кто вообще придумал умалчивать привидения типа от большого к меньшему без ошибки?

                            Про функции выше с "чёткой" семантикой шутку оценил. Тонко.
                            Ответить
          • > Утащил для наглядной демонстрации UB.
            Надо запилить сайт, на котором будет по примеру на каждый UB из стандарта с++ ;)
            Ответить
            • > Надо запилить сайт
              Говнокод?
              Ответить
              • Кто-то должен создать юзера UB, чтобы переписать туда примеры со стандарта.
                Ответить
              • Думаю на ideone не хватает комментов и тегов, например.
                Ответить
    • Бляя. Я ждал любого другого, но 255 это ВНЕЗАПНО.
      Ответить
    • СИШКОПРоБЛЕМЫ!
      Ответить
    • На чем лучше писать на c(++) под виндой?
      Ответить
      • Ясен пень на милашке
        Ответить
        • А что, милостивый государь, есьм "Милашка" ? Позвольте полюбопытстовать!..
          Ответить
          • Qt

            она же кьюююют
            Ответить
            • Я вообще-то IDE имел в виду.
              Ответить
              • для леденящего душу Qt только леденящий душу QtCreator
                Ответить
                • почему это
                  в студии кутэ тоже работает
                  дизайнер запускается, насколько я помню, отдельным окном, а так интеграция вполне себе на уровне, всякие эти ублюдошные moc из коробки по щелчку пальцев работают
                  Ответить
                  • > ублюдошные moc
                    Зато какая-никакая рефлексия. Классы по имени можно посоздавать, список свойств/слотов/инвокейблов у класса посмотреть, метод по имени инвокнуть и т.п. Тот же прилагаемый к Qt движок жабаскрипта юзает эту метаинфу, и любой QObject можно ему отдать на растерзание. За это, имхо, можно заплатить запуском препроцессора.
                    Ответить
                    • вот именно
                      докатились до того, что без жабаскрипта крестогуйприложения уже не могут
                      хотя их и крестами назвать сложно-то
                      Ответить
                      • > хотя их и крестами назвать сложно-то
                        А типа для крестогуя есть альтернатива? :)
                        Унылые wxWidgets? Ночной кошмар под названием MFC? Остается только делфи++ с покорёженным для совместимости с VCL языком...

                        > без жабаскрипта крестогуйприложения уже не могут
                        Да, печальная тенденция с этим Qt. Понеслись семимильными шагами в сторону QML и мобильных платформ ломая старые виджеты к хуям :( Глядя на последние версии плакать хочется.
                        Ответить
                        • У меня тут было небольшое приключение с линупсовым десктопом.

                          Сначала пытался допилить КуТ 5 приложение, но быстро это утомило, т.к. обилие школокода в нём зашкаливало, а понять логику создателей КуТ мне ну очень сложно.

                          Потом нашёл гномий аналог и допилил его. Но гномоделы оказались не менее упоротыми - для их поделок нужны распоследние версии гтк, не доступные даже на bleeding edge бубунте. А патчи они принимают в бугзиле эпохи динозавров и ну очень, очень нехотя.

                          В итоге пишу веб-аналог с Го-бэкэндом "чисто падсибя". Всего за несколько часов получилось запилить вполне себе работающий и полезный прототип. Ваяю нечёткий поиск по биграммам. Доволен как слон.
                          Ответить
                        • > А типа для крестогуя есть альтернатива? :)
                          это то и печально, что альтернативы то и нет

                          на самом деле на безрыбье и рыбу раком
                          я в том смысле, что Qt вполне можно пользоваться, особенно по сравнению с MFC
                          Ответить
                        • > Понеслись семимильными шагами в сторону QML
                          Ну и что ты там ниасилил? Юзай - не хочу. Норм штука. Туда все движется.
                          Ответить
                      • Ну а насчет жабаскрипта - ну всё лучше, чем велосипед, написанный на коленке сумрачным гением. Если по задаче надо хранить скрипты где-то вне проги (в субд, внешних файликах и т.п.) - то хоть убейся, а какой-то интерпретатор надо. И здесь либо парсер-генератор аля moc, либо бойлерплейт, третьего способа для интеграции крестов и скриптов тупо не существует :(

                        P.S. Хотя не, выход есть - не писать такие задачи на крестах.
                        Ответить

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